about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder.rs6
-rwxr-xr-xsrc/ci/init_repo.sh72
-rwxr-xr-xsrc/ci/run.sh10
-rw-r--r--src/liballoc/tests/slice.rs2
-rw-r--r--src/libcore/convert.rs25
-rw-r--r--src/libcore/iter/mod.rs2
-rw-r--r--src/libcore/num/mod.rs17
-rw-r--r--src/libcore/str/mod.rs31
-rw-r--r--src/libcore/sync/atomic.rs765
-rw-r--r--src/libcore/tests/ascii.rs3
-rw-r--r--src/librustc/dep_graph/dep_node.rs3
-rw-r--r--src/librustc/dep_graph/graph.rs7
-rw-r--r--src/librustc/dep_graph/prev.rs8
-rw-r--r--src/librustc/dep_graph/serialized.rs6
-rw-r--r--src/librustc/hir/lowering.rs4
-rw-r--r--src/librustc/hir/map/mod.rs1
-rw-r--r--src/librustc/hir/mod.rs1
-rw-r--r--src/librustc/ich/impls_hir.rs3
-rw-r--r--src/librustc/ty/maps/mod.rs4
-rw-r--r--src/librustc/ty/maps/plumbing.rs3
-rw-r--r--src/librustc_data_structures/indexed_vec.rs7
-rw-r--r--src/librustc_incremental/persist/save.rs2
-rw-r--r--src/librustc_mir/build/block.rs5
-rw-r--r--src/librustc_mir/interpret/const_eval.rs8
-rw-r--r--src/librustc_mir/interpret/place.rs32
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs14
-rw-r--r--src/librustc_passes/rvalue_promotion.rs12
-rw-r--r--src/librustc_resolve/resolve_imports.rs25
-rw-r--r--src/librustc_traits/lowering.rs49
-rw-r--r--src/librustc_trans/attributes.rs16
-rw-r--r--src/librustc_trans/builder.rs8
-rw-r--r--src/librustc_trans/llvm_util.rs14
-rw-r--r--src/librustc_trans_utils/symbol_names_test.rs21
-rw-r--r--src/librustc_typeck/check/mod.rs27
-rw-r--r--src/librustc_typeck/check/wfcheck.rs1026
-rw-r--r--src/librustdoc/clean/cfg.rs40
-rw-r--r--src/librustdoc/clean/mod.rs29
-rw-r--r--src/librustdoc/html/markdown.rs11
-rw-r--r--src/librustdoc/markdown.rs2
-rw-r--r--src/librustdoc/test.rs25
-rw-r--r--src/libstd/ascii.rs17
-rw-r--r--src/libstd/error.rs9
-rw-r--r--src/libstd/num.rs1
-rw-r--r--src/libstd/sys/windows/process.rs1
-rw-r--r--src/libstd/sys_common/wtf8.rs17
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/test.rs21
m---------src/stdsimd0
-rw-r--r--src/test/codegen/abi-main-signature-16bit-c-int.rs1
-rw-r--r--src/test/codegen/fastcall-inreg.rs2
-rw-r--r--src/test/codegen/global_asm.rs2
-rw-r--r--src/test/codegen/global_asm_include.rs2
-rw-r--r--src/test/codegen/global_asm_x2.rs2
-rw-r--r--src/test/codegen/repr-transparent-aggregates-1.rs1
-rw-r--r--src/test/run-make/tools.mk2
-rw-r--r--src/test/run-pass/issue-10683.rs2
-rw-r--r--src/test/run-pass/issue-27889.rs1
-rw-r--r--src/test/run-pass/issue-28561.rs2
-rw-r--r--src/test/rustdoc/check-styled-link.rs18
-rw-r--r--src/test/rustdoc/doc-cfg.rs24
-rw-r--r--src/test/ui/chalkify/lower_trait.rs22
-rw-r--r--src/test/ui/chalkify/lower_trait.stderr8
-rw-r--r--src/test/ui/type-dependent-def-issue-49241.rs15
-rw-r--r--src/test/ui/type-dependent-def-issue-49241.stderr18
-rw-r--r--src/tools/compiletest/src/runtest.rs7
-rw-r--r--src/tools/compiletest/src/util.rs33
66 files changed, 1447 insertions, 1129 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 3fd50f17ef3..a398bcc9737 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -310,12 +310,14 @@ impl<'a> Builder<'a> {
                 test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps,
                 test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty,
                 test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty,
-                test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake,
+                test::RunPassFullDepsPretty, test::RunFailFullDepsPretty,
                 test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck,
                 test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
                 test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
                 test::TheBook, test::UnstableBook,
-                test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
+                test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
+                // Run run-make last, since these won't pass without make on Windows
+                test::RunMake),
             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
index 8ab4276fa3b..f2664e6d196 100755
--- a/src/ci/init_repo.sh
+++ b/src/ci/init_repo.sh
@@ -17,6 +17,7 @@ ci_dir=$(cd $(dirname $0) && pwd)
 . "$ci_dir/shared.sh"
 
 travis_fold start init_repo
+travis_time_start
 
 REPO_DIR="$1"
 CACHE_DIR="$2"
@@ -42,54 +43,39 @@ if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then
   git fetch origin --unshallow beta master
 fi
 
-travis_fold start update_cache
-travis_time_start
-
-# Update the cache (a pristine copy of the rust source master)
-retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
-    git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir"
-if [ -d $cache_src_dir/src/llvm ]; then
-  (cd $cache_src_dir && git rm src/llvm)
-fi
-if [ -d $cache_src_dir/src/llvm-emscripten ]; then
-  (cd $cache_src_dir && git rm src/llvm-emscripten)
-fi
-retry sh -c "cd $cache_src_dir && \
-    git submodule deinit -f . && git submodule sync && git submodule update --init"
-
-travis_fold end update_cache
-travis_time_finish
+function fetch_submodule {
+    local module=$1
+    local cached="download-${module//\//-}.tar.gz"
+    retry sh -c "rm -f $cached && \
+        curl -sSL -o $cached $2"
+    mkdir $module
+    touch "$module/.git"
+    tar -C $module --strip-components=1 -xf $cached
+    rm $cached
+}
 
-travis_fold start update_submodules
-travis_time_start
-
-# Update the submodules of the repo we're in, using the pristine repo as
-# a cache for any object files
-# No, `git submodule foreach` won't work:
-# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
+included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example"
 modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
-for module in $modules; do
-    if [ "$module" = src/llvm ] || [ "$module" = src/llvm-emscripten ]; then
+modules=($modules)
+use_git=""
+urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)"
+urls=($urls)
+for i in ${!modules[@]}; do
+    module=${modules[$i]}
+    if [[ " $included " = *" $module "* ]]; then
         commit="$(git ls-tree HEAD $module | awk '{print $3}')"
         git rm $module
-        retry sh -c "rm -f $commit.tar.gz && \
-            curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
-        tar -C src/ -xf "$commit.tar.gz"
-        rm "$commit.tar.gz"
-        mv "src/llvm-$commit" $module
-        continue
-    fi
-    if [ ! -e "$cache_src_dir/$module/.git" ]; then
-        echo "WARNING: $module not found in pristine repo"
-        retry sh -c "git submodule deinit -f $module && \
-            git submodule update --init --recursive $module"
+        url=${urls[$i]}
+        url=${url/\.git/}
+        fetch_submodule $module "$url/archive/$commit.tar.gz" &
         continue
+    else
+        use_git="$use_git $module"
     fi
-    retry sh -c "git submodule deinit -f $module && \
-        git submodule update --init --recursive --reference $cache_src_dir/$module $module"
 done
-
-travis_fold end update_submodules
-travis_time_finish
-
+retry sh -c "git submodule deinit -f $use_git && \
+    git submodule sync && \
+    git submodule update -j 16 --init --recursive $use_git"
+wait
 travis_fold end init_repo
+travis_time_finish
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 5d5965f561a..9a26043c92c 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -107,15 +107,7 @@ fi
 travis_fold end log-system-info
 
 if [ ! -z "$SCRIPT" ]; then
-  # FIXME(#49246): Re-enable these tools after #49246 has been merged and thus fixing the cache.
-  if [ "$DEPLOY_ALT" = 1 ]; then
-    sh -x -c "$SCRIPT \
-       --exclude src/tools/rls \
-       --exclude src/tools/rustfmt \
-       --exclude src/tools/clippy"
-  else
-    sh -x -c "$SCRIPT"
-  fi
+  sh -x -c "$SCRIPT"
 else
   do_make() {
     travis_fold start "make-$1"
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index d9e9d91cea8..3f679d81f08 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -1351,7 +1351,7 @@ fn test_copy_from_slice_dst_shorter() {
 const MAX_LEN: usize = 80;
 
 static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
-    // FIXME #5244: AtomicUsize is not Copy.
+    // FIXME(RFC 1109): AtomicUsize is not Copy.
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index d3a83dc795c..7324df95bc5 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -48,25 +48,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fmt;
-
-/// A type used as the error type for implementations of fallible conversion
-/// traits in cases where conversions cannot actually fail.
-///
-/// Because `Infallible` has no variants, a value of this type can never exist.
-/// It is used only to satisfy trait signatures that expect an error type, and
-/// signals to both the compiler and the user that the error case is impossible.
-#[unstable(feature = "try_from", issue = "33417")]
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub enum Infallible {}
-
-#[unstable(feature = "try_from", issue = "33417")]
-impl fmt::Display for Infallible {
-    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-        }
-    }
-}
 /// A cheap reference-to-reference conversion. Used to convert a value to a
 /// reference value within generic code.
 ///
@@ -382,7 +363,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U>
     }
 }
 
-// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
+// FIXME (#45742): replace the above impls for &/&mut with the following more general one:
 // // As lifts over Deref
 // impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
 //     fn as_ref(&self) -> &U {
@@ -399,7 +380,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U>
     }
 }
 
-// FIXME (#23442): replace the above impl for &mut with the following more general one:
+// FIXME (#45742): replace the above impl for &mut with the following more general one:
 // // AsMut lifts over DerefMut
 // impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
 //     fn as_mut(&mut self) -> &mut U {
@@ -438,7 +419,7 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
 // with an uninhabited error type.
 #[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryFrom<U> for T where T: From<U> {
-    type Error = Infallible;
+    type Error = !;
 
     fn try_from(value: U) -> Result<Self, Self::Error> {
         Ok(T::from(value))
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index b1b783b47c7..1e8476d3880 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -1872,7 +1872,7 @@ impl<I: Iterator> Iterator for Peekable<I> {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        // FIXME(#6393): merge these when borrow-checking gets better.
+        // FIXME(#43234): merge these when borrow-checking gets better.
         if n == 0 {
             match self.peeked.take() {
                 Some(v) => v,
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 09ab7060d37..4583e45bb12 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -12,7 +12,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use convert::{Infallible, TryFrom};
+use convert::TryFrom;
 use fmt;
 use intrinsics;
 use ops;
@@ -3596,10 +3596,9 @@ impl fmt::Display for TryFromIntError {
 }
 
 #[unstable(feature = "try_from", issue = "33417")]
-impl From<Infallible> for TryFromIntError {
-    fn from(infallible: Infallible) -> TryFromIntError {
-        match infallible {
-        }
+impl From<!> for TryFromIntError {
+    fn from(never: !) -> TryFromIntError {
+        never
     }
 }
 
@@ -3608,7 +3607,7 @@ macro_rules! try_from_unbounded {
     ($source:ty, $($target:ty),*) => {$(
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
-            type Error = Infallible;
+            type Error = !;
 
             #[inline]
             fn try_from(value: $source) -> Result<Self, Self::Error> {
@@ -3719,7 +3718,7 @@ try_from_lower_bounded!(isize, usize);
 #[cfg(target_pointer_width = "16")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::{Infallible, TryFrom};
+    use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8);
     try_from_unbounded!(usize, u16, u32, u64, u128);
@@ -3745,7 +3744,7 @@ mod ptr_try_from_impls {
 #[cfg(target_pointer_width = "32")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::{Infallible, TryFrom};
+    use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8, u16);
     try_from_unbounded!(usize, u32, u64, u128);
@@ -3771,7 +3770,7 @@ mod ptr_try_from_impls {
 #[cfg(target_pointer_width = "64")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::{Infallible, TryFrom};
+    use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8, u16, u32);
     try_from_unbounded!(usize, u64, u128);
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 9cf862bd936..1185b7acaae 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -165,6 +165,37 @@ Section: Creating a string
 ///
 /// [`String`]: ../../std/string/struct.String.html#method.from_utf8
 /// [`&str`]: ../../std/str/fn.from_utf8.html
+///
+/// # Examples
+///
+/// This error type’s methods can be used to create functionality
+/// similar to `String::from_utf8_lossy` without allocating heap memory:
+///
+/// ```
+/// fn from_utf8_lossy<F>(mut input: &[u8], mut push: F) where F: FnMut(&str) {
+///     loop {
+///         match ::std::str::from_utf8(input) {
+///             Ok(valid) => {
+///                 push(valid);
+///                 break
+///             }
+///             Err(error) => {
+///                 let (valid, after_valid) = input.split_at(error.valid_up_to());
+///                 unsafe {
+///                     push(::std::str::from_utf8_unchecked(valid))
+///                 }
+///                 push("\u{FFFD}");
+///
+///                 if let Some(invalid_sequence_length) = error.error_len() {
+///                     input = &after_valid[invalid_sequence_length..]
+///                 } else {
+///                     break
+///                 }
+///             }
+///         }
+///     }
+/// }
+/// ```
 #[derive(Copy, Eq, PartialEq, Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Utf8Error {
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 25827edee7d..fe5ed5d4942 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -948,6 +948,7 @@ macro_rules! atomic_int {
      $stable_from:meta,
      $stable_nand:meta,
      $s_int_type:expr, $int_ref:expr,
+     $extra_feature:expr,
      $int_type:ident $atomic_type:ident $atomic_init:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
@@ -959,12 +960,7 @@ macro_rules! atomic_int {
         /// ). For more about the differences between atomic types and
         /// non-atomic types, please see the [module-level documentation].
         ///
-        /// Please note that examples are shared between atomic variants of
-        /// primitive integer types, so it's normal that they are all
-        /// demonstrating [`AtomicIsize`].
-        ///
         /// [module-level documentation]: index.html
-        /// [`AtomicIsize`]: struct.AtomicIsize.html
         #[$stable]
         pub struct $atomic_type {
             v: UnsafeCell<$int_type>,
@@ -1001,395 +997,426 @@ macro_rules! atomic_int {
         unsafe impl Sync for $atomic_type {}
 
         impl $atomic_type {
-            /// Creates a new atomic integer.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::AtomicIsize;
-            ///
-            /// let atomic_forty_two  = AtomicIsize::new(42);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub const fn new(v: $int_type) -> Self {
-                $atomic_type {v: UnsafeCell::new(v)}
+            doc_comment! {
+                concat!("Creates a new atomic integer.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+
+let atomic_forty_two = ", stringify!($atomic_type), "::new(42);
+```"),
+                #[inline]
+                #[$stable]
+                pub const fn new(v: $int_type) -> Self {
+                    $atomic_type {v: UnsafeCell::new(v)}
+                }
             }
 
-            /// Returns a mutable reference to the underlying integer.
-            ///
-            /// This is safe because the mutable reference guarantees that no other threads are
-            /// concurrently accessing the atomic data.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let mut some_isize = AtomicIsize::new(10);
-            /// assert_eq!(*some_isize.get_mut(), 10);
-            /// *some_isize.get_mut() = 5;
-            /// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
-            /// ```
-            #[inline]
-            #[$stable_access]
-            pub fn get_mut(&mut self) -> &mut $int_type {
-                unsafe { &mut *self.v.get() }
+            doc_comment! {
+                concat!("Returns a mutable reference to the underlying integer.
+
+This is safe because the mutable reference guarantees that no other threads are
+concurrently accessing the atomic data.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let mut some_var = ", stringify!($atomic_type), "::new(10);
+assert_eq!(*some_var.get_mut(), 10);
+*some_var.get_mut() = 5;
+assert_eq!(some_var.load(Ordering::SeqCst), 5);
+```"),
+                #[inline]
+                #[$stable_access]
+                pub fn get_mut(&mut self) -> &mut $int_type {
+                    unsafe { &mut *self.v.get() }
+                }
             }
 
-            /// Consumes the atomic and returns the contained value.
-            ///
-            /// This is safe because passing `self` by value guarantees that no other threads are
-            /// concurrently accessing the atomic data.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::AtomicIsize;
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            /// assert_eq!(some_isize.into_inner(), 5);
-            /// ```
-            #[inline]
-            #[$stable_access]
-            pub fn into_inner(self) -> $int_type {
-                self.v.into_inner()
+            doc_comment! {
+                concat!("Consumes the atomic and returns the contained value.
+
+This is safe because passing `self` by value guarantees that no other threads are
+concurrently accessing the atomic data.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+assert_eq!(some_var.into_inner(), 5);
+```"),
+                #[inline]
+                #[$stable_access]
+                pub fn into_inner(self) -> $int_type {
+                    self.v.into_inner()
+                }
             }
 
-            /// Loads a value from the atomic integer.
-            ///
-            /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// # Panics
-            ///
-            /// Panics if `order` is [`Release`] or [`AcqRel`].
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn load(&self, order: Ordering) -> $int_type {
-                unsafe { atomic_load(self.v.get(), order) }
+            doc_comment! {
+                concat!("Loads a value from the atomic integer.
+
+`load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+# Panics
+
+Panics if `order` is [`Release`] or [`AcqRel`].
+
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.load(Ordering::Relaxed), 5);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn load(&self, order: Ordering) -> $int_type {
+                    unsafe { atomic_load(self.v.get(), order) }
+                }
             }
 
-            /// Stores a value into the atomic integer.
-            ///
-            /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// some_isize.store(10, Ordering::Relaxed);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            ///
-            /// # Panics
-            ///
-            /// Panics if `order` is [`Acquire`] or [`AcqRel`].
-            ///
-            /// [`Acquire`]: enum.Ordering.html#variant.Acquire
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            #[inline]
-            #[$stable]
-            pub fn store(&self, val: $int_type, order: Ordering) {
-                unsafe { atomic_store(self.v.get(), val, order); }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer.
+
+`store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+some_var.store(10, Ordering::Relaxed);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```
+
+# Panics
+
+Panics if `order` is [`Acquire`] or [`AcqRel`].
+
+[`Acquire`]: enum.Ordering.html#variant.Acquire
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel"),
+                #[inline]
+                #[$stable]
+                pub fn store(&self, val: $int_type, order: Ordering) {
+                    unsafe { atomic_store(self.v.get(), val, order); }
+                }
             }
 
-            /// Stores a value into the atomic integer, returning the previous value.
-            ///
-            /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_swap(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer, returning the previous value.
+
+`swap` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_swap(self.v.get(), val, order) }
+                }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// The return value is always the previous value. If it is equal to `current`, then the
-            /// value was updated.
-            ///
-            /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
-            /// ordering of this operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            ///
-            /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn compare_and_swap(&self,
-                                    current: $int_type,
-                                    new: $int_type,
-                                    order: Ordering) -> $int_type {
-                match self.compare_exchange(current,
-                                            new,
-                                            order,
-                                            strongest_failure_ordering(order)) {
-                    Ok(x) => x,
-                    Err(x) => x,
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+The return value is always the previous value. If it is equal to `current`, then the
+value was updated.
+
+`compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+
+assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn compare_and_swap(&self,
+                                        current: $int_type,
+                                        new: $int_type,
+                                        order: Ordering) -> $int_type {
+                    match self.compare_exchange(current,
+                                                new,
+                                                order,
+                                                strongest_failure_ordering(order)) {
+                        Ok(x) => x,
+                        Err(x) => x,
+                    }
                 }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// The return value is a result indicating whether the new value was written and
-            /// containing the previous value. On success this value is guaranteed to be equal to
-            /// `current`.
-            ///
-            /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
-            /// ordering of this operation. The first describes the required ordering if
-            /// the operation succeeds while the second describes the required ordering when
-            /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
-            /// must be equivalent or weaker than the success ordering.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.compare_exchange(5, 10,
-            ///                                        Ordering::Acquire,
-            ///                                        Ordering::Relaxed),
-            ///            Ok(5));
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            ///
-            /// assert_eq!(some_isize.compare_exchange(6, 12,
-            ///                                        Ordering::SeqCst,
-            ///                                        Ordering::Acquire),
-            ///            Err(10));
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            #[inline]
-            #[$stable_cxchg]
-            pub fn compare_exchange(&self,
-                                    current: $int_type,
-                                    new: $int_type,
-                                    success: Ordering,
-                                    failure: Ordering) -> Result<$int_type, $int_type> {
-                unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+The return value is a result indicating whether the new value was written and
+containing the previous value. On success this value is guaranteed to be equal to
+`current`.
+
+`compare_exchange` takes two [`Ordering`] arguments to describe the memory
+ordering of this operation. The first describes the required ordering if
+the operation succeeds while the second describes the required ordering when
+the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+must be equivalent or weaker than the success ordering.
+
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.compare_exchange(5, 10,
+                                     Ordering::Acquire,
+                                     Ordering::Relaxed),
+           Ok(5));
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+
+assert_eq!(some_var.compare_exchange(6, 12,
+                                     Ordering::SeqCst,
+                                     Ordering::Acquire),
+           Err(10));
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```"),
+                #[inline]
+                #[$stable_cxchg]
+                pub fn compare_exchange(&self,
+                                        current: $int_type,
+                                        new: $int_type,
+                                        success: Ordering,
+                                        failure: Ordering) -> Result<$int_type, $int_type> {
+                    unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+                }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
-            /// when the comparison succeeds, which can result in more efficient code on some
-            /// platforms. The return value is a result indicating whether the new value was
-            /// written and containing the previous value.
-            ///
-            /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
-            /// ordering of this operation. The first describes the required ordering if the
-            /// operation succeeds while the second describes the required ordering when the
-            /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
-            /// must be equivalent or weaker than the success ordering.
-            ///
-            /// [`compare_exchange`]: #method.compare_exchange
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let val = AtomicIsize::new(4);
-            ///
-            /// let mut old = val.load(Ordering::Relaxed);
-            /// loop {
-            ///     let new = old * 2;
-            ///     match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
-            ///         Ok(_) => break,
-            ///         Err(x) => old = x,
-            ///     }
-            /// }
-            /// ```
-            #[inline]
-            #[$stable_cxchg]
-            pub fn compare_exchange_weak(&self,
-                                         current: $int_type,
-                                         new: $int_type,
-                                         success: Ordering,
-                                         failure: Ordering) -> Result<$int_type, $int_type> {
-                unsafe {
-                    atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+Unlike [`compare_exchange`], this function is allowed to spuriously fail even
+when the comparison succeeds, which can result in more efficient code on some
+platforms. The return value is a result indicating whether the new value was
+written and containing the previous value.
+
+`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
+ordering of this operation. The first describes the required ordering if the
+operation succeeds while the second describes the required ordering when the
+operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+must be equivalent or weaker than the success ordering.
+
+[`compare_exchange`]: #method.compare_exchange
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let val = ", stringify!($atomic_type), "::new(4);
+
+let mut old = val.load(Ordering::Relaxed);
+loop {
+    let new = old * 2;
+    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+        Ok(_) => break,
+        Err(x) => old = x,
+    }
+}
+```"),
+                #[inline]
+                #[$stable_cxchg]
+                pub fn compare_exchange_weak(&self,
+                                             current: $int_type,
+                                             new: $int_type,
+                                             success: Ordering,
+                                             failure: Ordering) -> Result<$int_type, $int_type> {
+                    unsafe {
+                        atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+                    }
                 }
             }
 
-            /// Adds to the current value, returning the previous value.
-            ///
-            /// This operation wraps around on overflow.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0);
-            /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_add(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Adds to the current value, returning the previous value.
+
+This operation wraps around on overflow.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0);
+assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
+assert_eq!(foo.load(Ordering::SeqCst), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_add(self.v.get(), val, order) }
+                }
             }
 
-            /// Subtracts from the current value, returning the previous value.
-            ///
-            /// This operation wraps around on overflow.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0);
-            /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
-            /// assert_eq!(foo.load(Ordering::SeqCst), -10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_sub(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Subtracts from the current value, returning the previous value.
+
+This operation wraps around on overflow.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(20);
+assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
+assert_eq!(foo.load(Ordering::SeqCst), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_sub(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "and" with the current value.
-            ///
-            /// Performs a bitwise "and" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
-            #[inline]
-            #[$stable]
-            pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_and(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"and\" with the current value.
+
+Performs a bitwise \"and\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_and(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "nand" with the current value.
-            ///
-            /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// #![feature(atomic_nand)]
-            ///
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0xf731);
-            /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731);
-            /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f));
-            #[inline]
-            #[$stable_nand]
-            pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_nand(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"nand\" with the current value.
+
+Performs a bitwise \"nand\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "#![feature(atomic_nand)]
+
+use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0x13);
+assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
+assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
+```"),
+                #[inline]
+                #[$stable_nand]
+                pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_nand(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "or" with the current value.
-            ///
-            /// Performs a bitwise "or" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
-            #[inline]
-            #[$stable]
-            pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_or(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"or\" with the current value.
+
+Performs a bitwise \"or\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_or(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "xor" with the current value.
-            ///
-            /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
-            #[inline]
-            #[$stable]
-            pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_xor(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"xor\" with the current value.
+
+Performs a bitwise \"xor\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_xor(self.v.get(), val, order) }
+                }
             }
         }
     }
@@ -1404,6 +1431,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i8", "../../../std/primitive.i8.html",
+    "#![feature(integer_atomics)]\n\n",
     i8 AtomicI8 ATOMIC_I8_INIT
 }
 #[cfg(target_has_atomic = "8")]
@@ -1415,6 +1443,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u8", "../../../std/primitive.u8.html",
+    "#![feature(integer_atomics)]\n\n",
     u8 AtomicU8 ATOMIC_U8_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1426,6 +1455,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i16", "../../../std/primitive.i16.html",
+    "#![feature(integer_atomics)]\n\n",
     i16 AtomicI16 ATOMIC_I16_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1437,6 +1467,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u16", "../../../std/primitive.u16.html",
+    "#![feature(integer_atomics)]\n\n",
     u16 AtomicU16 ATOMIC_U16_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1448,6 +1479,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i32", "../../../std/primitive.i32.html",
+    "#![feature(integer_atomics)]\n\n",
     i32 AtomicI32 ATOMIC_I32_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1459,6 +1491,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u32", "../../../std/primitive.u32.html",
+    "#![feature(integer_atomics)]\n\n",
     u32 AtomicU32 ATOMIC_U32_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1470,6 +1503,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i64", "../../../std/primitive.i64.html",
+    "#![feature(integer_atomics)]\n\n",
     i64 AtomicI64 ATOMIC_I64_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1481,6 +1515,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u64", "../../../std/primitive.u64.html",
+    "#![feature(integer_atomics)]\n\n",
     u64 AtomicU64 ATOMIC_U64_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1492,6 +1527,7 @@ atomic_int!{
     stable(feature = "atomic_from", since = "1.23.0"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "isize", "../../../std/primitive.isize.html",
+    "",
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1503,6 +1539,7 @@ atomic_int!{
     stable(feature = "atomic_from", since = "1.23.0"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "usize", "../../../std/primitive.usize.html",
+    "",
     usize AtomicUsize ATOMIC_USIZE_INIT
 }
 
diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs
index 4d43067ad2c..950222dbcfa 100644
--- a/src/libcore/tests/ascii.rs
+++ b/src/libcore/tests/ascii.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use core::char::from_u32;
-use std::ascii::AsciiExt;
 
 #[test]
 fn test_is_ascii() {
@@ -143,8 +142,6 @@ macro_rules! assert_all {
                            stringify!($what), b);
                 }
             }
-            assert!($str.$what());
-            assert!($str.as_bytes().$what());
         )+
     }};
     ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 744e3a5eaab..1e2e4e5a69f 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -579,6 +579,9 @@ define_dep_nodes!( <'tcx>
     [] GetPanicStrategy(CrateNum),
     [] IsNoBuiltins(CrateNum),
     [] ImplDefaultness(DefId),
+    [] CheckItemWellFormed(DefId),
+    [] CheckTraitItemWellFormed(DefId),
+    [] CheckImplItemWellFormed(DefId),
     [] ReachableNonGenerics(CrateNum),
     [] NativeLibraries(CrateNum),
     [] PluginRegistrarFn(CrateNum),
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 0ad79eacd2b..d60c22064d3 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -476,10 +476,8 @@ impl DepGraph {
             fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO);
         }
 
-        let nodes: IndexVec<_, (DepNode, Fingerprint)> =
-            current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| {
-            (dep_node, fingerprints[idx])
-        }).collect();
+        let fingerprints = fingerprints.clone().convert_index_type();
+        let nodes = current_dep_graph.nodes.clone().convert_index_type();
 
         let total_edge_count: usize = current_dep_graph.edges.iter()
                                                              .map(|v| v.len())
@@ -503,6 +501,7 @@ impl DepGraph {
 
         SerializedDepGraph {
             nodes,
+            fingerprints,
             edge_list_indices,
             edge_list_data,
         }
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
index 504b60e763e..669a99019aa 100644
--- a/src/librustc/dep_graph/prev.rs
+++ b/src/librustc/dep_graph/prev.rs
@@ -23,7 +23,7 @@ impl PreviousDepGraph {
     pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
         let index: FxHashMap<_, _> = data.nodes
             .iter_enumerated()
-            .map(|(idx, &(dep_node, _))| (dep_node, idx))
+            .map(|(idx, &dep_node)| (dep_node, idx))
             .collect();
         PreviousDepGraph { data, index }
     }
@@ -41,7 +41,7 @@ impl PreviousDepGraph {
 
     #[inline]
     pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode {
-        self.data.nodes[dep_node_index].0
+        self.data.nodes[dep_node_index]
     }
 
     #[inline]
@@ -58,14 +58,14 @@ impl PreviousDepGraph {
     pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
         self.index
             .get(dep_node)
-            .map(|&node_index| self.data.nodes[node_index].1)
+            .map(|&node_index| self.data.fingerprints[node_index])
     }
 
     #[inline]
     pub fn fingerprint_by_index(&self,
                                 dep_node_index: SerializedDepNodeIndex)
                                 -> Fingerprint {
-        self.data.nodes[dep_node_index].1
+        self.data.fingerprints[dep_node_index]
     }
 
     pub fn node_count(&self) -> usize {
diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs
index c96040ab9b6..60fc813a25d 100644
--- a/src/librustc/dep_graph/serialized.rs
+++ b/src/librustc/dep_graph/serialized.rs
@@ -20,7 +20,10 @@ newtype_index!(SerializedDepNodeIndex);
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedDepGraph {
     /// The set of all DepNodes in the graph
-    pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>,
+    pub nodes: IndexVec<SerializedDepNodeIndex, DepNode>,
+    /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
+    /// the DepNode at the same index in the nodes vector.
+    pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
     /// For each DepNode, stores the list of edges originating from that
     /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
     /// which holds the actual DepNodeIndices of the target nodes.
@@ -35,6 +38,7 @@ impl SerializedDepGraph {
     pub fn new() -> SerializedDepGraph {
         SerializedDepGraph {
             nodes: IndexVec::new(),
+            fingerprints: IndexVec::new(),
             edge_list_indices: IndexVec::new(),
             edge_list_data: Vec::new(),
         }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 1439410f7e9..f6bdfde15fc 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -809,7 +809,7 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
+    fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
         attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into()
     }
 
@@ -1019,6 +1019,7 @@ impl<'a> LoweringContext<'a> {
                             span,
                             pure_wrt_drop: false,
                             synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+                            attrs: P::new(),
                         });
 
                         hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
@@ -1585,6 +1586,7 @@ impl<'a> LoweringContext<'a> {
                                .filter(|attr| attr.check_name("rustc_synthetic"))
                                .map(|_| hir::SyntheticTyParamKind::ImplTrait)
                                .nth(0),
+            attrs: self.lower_attrs(&tp.attrs),
         }
     }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 61fae4609d5..e8bcbfbb77a 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -962,6 +962,7 @@ impl<'hir> Map<'hir> {
             Some(NodeField(ref f)) => Some(&f.attrs[..]),
             Some(NodeExpr(ref e)) => Some(&*e.attrs),
             Some(NodeStmt(ref s)) => Some(s.node.attrs()),
+            Some(NodeTyParam(tp)) => Some(&tp.attrs[..]),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
             Some(NodeStructCtor(_)) => {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 5ae84f5685e..d6810b2468b 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -414,6 +414,7 @@ pub struct TyParam {
     pub span: Span,
     pub pure_wrt_drop: bool,
     pub synthetic: Option<SyntheticTyParamKind>,
+    pub attrs: HirVec<Attribute>,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index e764cedd658..774b1442b71 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -203,7 +203,8 @@ impl_stable_hash_for!(struct hir::TyParam {
     default,
     span,
     pure_wrt_drop,
-    synthetic
+    synthetic,
+    attrs
 });
 
 impl_stable_hash_for!(enum hir::GenericParam {
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index b6b7361bb2f..6c3b4efb932 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -299,6 +299,10 @@ define_maps! { <'tcx>
 
     [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
 
+    [] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (),
+    [] fn check_trait_item_well_formed: CheckTraitItemWellFormed(DefId) -> (),
+    [] fn check_impl_item_well_formed: CheckImplItemWellFormed(DefId) -> (),
+
     // The DefIds of all non-generic functions and statics in the given crate
     // that can be reached from outside the crate.
     //
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index c5146790425..4170fa76797 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -871,6 +871,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
         DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
         DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
+        DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); }
+        DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
+        DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
         DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
         DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
         DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index a5b1a7e57ab..cbb3ff51715 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -503,6 +503,13 @@ impl<I: Idx, T> IndexVec<I, T> {
             (c1, c2)
         }
     }
+
+    pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
+        IndexVec {
+            raw: self.raw,
+            _marker: PhantomData,
+        }
+    }
 }
 
 impl<I: Idx, T: Clone> IndexVec<I, T> {
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index ca1e3563089..a5bc1106ba0 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -162,7 +162,7 @@ fn encode_dep_graph(tcx: TyCtxt,
 
         let mut counts: FxHashMap<_, Stat> = FxHashMap();
 
-        for (i, &(node, _)) in serialized_graph.nodes.iter_enumerated() {
+        for (i, &node) in serialized_graph.nodes.iter_enumerated() {
             let stat = counts.entry(node.kind).or_insert(Stat {
                 kind: node.kind,
                 node_counter: 0,
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index ef30b1e4522..7281fb59663 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -117,10 +117,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
                         unpack!(block = this.in_opt_scope(
-                            opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
+                            opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
                                 let scope = (init_scope, source_info);
-                                this.in_scope(scope, lint_level, block, move |this| {
-                                    // FIXME #30046                             ^~~~
+                                this.in_scope(scope, lint_level, block, |this| {
                                     this.expr_into_pattern(block, pattern, init)
                                 })
                             }));
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 82eb28287b0..47f6f61072e 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -339,6 +339,14 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         cid: GlobalId<'tcx>,
     ) -> EvalResult<'tcx, AllocId> {
+        let alloc = ecx
+                    .tcx
+                    .interpret_interner
+                    .get_cached(cid.instance.def_id());
+        // Don't evaluate when already cached to prevent cycles
+        if let Some(alloc) = alloc {
+            return Ok(alloc)
+        }
         // ensure the static is computed
         ecx.const_eval(cid)?;
         Ok(ecx
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index d27de3ef6bf..456f5fd75db 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -197,29 +197,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             },
 
             Static(ref static_) => {
-                let alloc = self
-                    .tcx
-                    .interpret_interner
-                    .get_cached(static_.def_id);
                 let layout = self.layout_of(self.place_ty(mir_place))?;
-                if let Some(alloc) = alloc {
-                    Place::Ptr {
-                        ptr: MemoryPointer::new(alloc, 0).into(),
-                        align: layout.align,
-                        extra: PlaceExtra::None,
-                    }
-                } else {
-                    let instance = ty::Instance::mono(*self.tcx, static_.def_id);
-                    let cid = GlobalId {
-                        instance,
-                        promoted: None
-                    };
-                    let alloc = Machine::init_static(self, cid)?;
-                    Place::Ptr {
-                        ptr: MemoryPointer::new(alloc, 0).into(),
-                        align: layout.align,
-                        extra: PlaceExtra::None,
-                    }
+                let instance = ty::Instance::mono(*self.tcx, static_.def_id);
+                let cid = GlobalId {
+                    instance,
+                    promoted: None
+                };
+                let alloc = Machine::init_static(self, cid)?;
+                Place::Ptr {
+                    ptr: MemoryPointer::new(alloc, 0).into(),
+                    align: layout.align,
+                    extra: PlaceExtra::None,
                 }
             }
 
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index e95126c8a1a..19f33ef5d45 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -177,7 +177,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 });
             }
             DropStyle::Conditional => {
-                let unwind = self.unwind; // FIXME(#6393)
+                let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 let drop_bb = self.complete_drop(Some(DropFlagMode::Deep), succ, unwind);
                 self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
@@ -268,7 +268,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         // Clear the "master" drop flag at the end. This is needed
         // because the "master" drop protects the ADT's discriminant,
         // which is invalidated after the ADT is dropped.
-        let (succ, unwind) = (self.succ, self.unwind); // FIXME(#6393)
+        let (succ, unwind) = (self.succ, self.unwind); // FIXME(#43234)
         (
             self.drop_flag_reset_block(DropFlagMode::Shallow, succ, unwind),
             unwind.map(|unwind| {
@@ -344,7 +344,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         let interior = self.place.clone().deref();
         let interior_path = self.elaborator.deref_subpath(self.path);
 
-        let succ = self.succ; // FIXME(#6393)
+        let succ = self.succ; // FIXME(#43234)
         let unwind = self.unwind;
         let succ = self.box_free_block(ty, succ, unwind);
         let unwind_succ = self.unwind.map(|unwind| {
@@ -717,7 +717,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                            ptr_based)
         });
 
-        let succ = self.succ; // FIXME(#6393)
+        let succ = self.succ; // FIXME(#43234)
         let loop_block = self.drop_loop(
             succ,
             cur,
@@ -798,7 +798,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 self.open_drop_for_adt(def, substs)
             }
             ty::TyDynamic(..) => {
-                let unwind = self.unwind; // FIXME(#6393)
+                let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
             }
@@ -849,7 +849,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
 
     fn elaborated_drop_block<'a>(&mut self) -> BasicBlock {
         debug!("elaborated_drop_block({:?})", self);
-        let unwind = self.unwind; // FIXME(#6393)
+        let unwind = self.unwind; // FIXME(#43234)
         let succ = self.succ;
         let blk = self.drop_block(succ, unwind);
         self.elaborate_drop(blk);
@@ -882,7 +882,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             args: vec![Operand::Move(self.place.clone())],
             destination: Some((unit_temp, target)),
             cleanup: None
-        }; // FIXME(#6393)
+        }; // FIXME(#43234)
         let free_block = self.new_block(unwind, call);
 
         let block_start = Location { block: free_block, statement_index: 0 };
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 356ad9ec11b..76cbc670969 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -373,10 +373,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             }
         }
         hir::ExprMethodCall(..) => {
-            let def_id = v.tables.type_dependent_defs()[e.hir_id].def_id();
-            match v.tcx.associated_item(def_id).container {
-                ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
-                ty::TraitContainer(_) => v.promotable = false
+            if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) {
+                let def_id = def.def_id();
+                match v.tcx.associated_item(def_id).container {
+                    ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
+                    ty::TraitContainer(_) => v.promotable = false
+                }
+            } else {
+                v.tcx.sess.delay_span_bug(e.span, "no type-dependent def for method call");
             }
         }
         hir::ExprStruct(..) => {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 4cbebdc3c1c..644a2ffe3c3 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1025,28 +1025,9 @@ fn import_path_to_string(names: &[SpannedIdent],
         if names.is_empty() {
             import_directive_subclass_to_string(subclass)
         } else {
-            // FIXME: Remove this entire logic after #48116 is fixed.
-            //
-            // Note that this code looks a little wonky, it's currently here to
-            // hopefully help debug #48116, but otherwise isn't intended to
-            // cause any problems.
-            let x = format!(
-                "{}::{}",
-                names_to_string(names),
-                import_directive_subclass_to_string(subclass),
-            );
-            if names.is_empty() || x.starts_with("::") {
-                span_bug!(
-                    span,
-                    "invalid name `{}` at {:?}; global = {}, names = {:?}, subclass = {:?}",
-                    x,
-                    span,
-                    global,
-                    names,
-                    subclass
-                );
-            }
-            return x
+            format!("{}::{}",
+                    names_to_string(names),
+                    import_directive_subclass_to_string(subclass))
         }
     }
 }
diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs
index c9666f55d44..1092e826a35 100644
--- a/src/librustc_traits/lowering.rs
+++ b/src/librustc_traits/lowering.rs
@@ -12,6 +12,7 @@ use rustc::hir::{self, ImplPolarity};
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::subst::Substs;
 use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
 use syntax::ast;
 use rustc_data_structures::sync::Lrc;
@@ -104,6 +105,7 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = tcx.hir.expect_item(node_id);
     match item.node {
+        hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
         hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
 
         // FIXME: other constructions e.g. traits, associated types...
@@ -111,6 +113,36 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     }
 }
 
+fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> Lrc<Vec<Clause<'tcx>>>
+{
+    // Rule Implemented-From-Env (see rustc guide)
+    //
+    // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
+    //
+    // ```
+    // forall<Self, P1..Pn> {
+    //   Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)
+    // }
+    // ```
+
+    // `Self: Trait<P1..Pn>`
+    let trait_pred = ty::TraitPredicate {
+        trait_ref: ty::TraitRef {
+            def_id,
+            substs: Substs::identity_for_item(tcx, def_id)
+        }
+    };
+    // `FromEnv(Self: Trait<P1..Pn>)`
+    let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower()));
+    // `Implemented(Self: Trait<P1..Pn>)`
+    let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
+
+    // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
+    let clause = Clause::Implies(vec![from_env], impl_trait);
+    Lrc::new(vec![clause])
+}
+
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     -> Lrc<Vec<Clause<'tcx>>>
 {
@@ -118,15 +150,24 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
         return Lrc::new(vec![]);
     }
 
-    // Rule Implemented-From-Impl
+    // Rule Implemented-From-Impl (see rustc guide)
+    //
+    // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
     //
-    // (see rustc guide)
+    // ```
+    // forall<P0..Pn> {
+    //   Implemented(A0: Trait<A1..An>) :- WC
+    // }
+    // ```
 
     let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
-    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
+    // `Implemented(A0: Trait<A1..An>)`
+    let trait_pred = ty::TraitPredicate { trait_ref }.lower();
+     // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates.lower();
 
-    let clause = Clause::Implies(where_clauses, trait_ref);
+     // `Implemented(A0: Trait<A1..An>) :- WC`
+    let clause = Clause::Implies(where_clauses, trait_pred);
     Lrc::new(vec![clause])
 }
 
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index d5ec8d1b552..040d9455334 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -148,9 +148,17 @@ fn cstr(s: &'static str) -> &CStr {
 pub fn provide(providers: &mut Providers) {
     providers.target_features_whitelist = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
-            .iter()
-            .map(|c| c.to_string())
-            .collect())
+        if tcx.sess.opts.actually_rustdoc {
+            // rustdoc needs to be able to document functions that use all the features, so
+            // whitelist them all
+            Lrc::new(llvm_util::all_known_features()
+                .map(|c| c.to_string())
+                .collect())
+        } else {
+            Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
+                .iter()
+                .map(|c| c.to_string())
+                .collect())
+        }
     };
 }
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 3f5a9a54ff1..91eabb9998f 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmin");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true);
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
             }
@@ -1046,7 +1046,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmax");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true);
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
             }
@@ -1056,7 +1056,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmin_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false);
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
             }
@@ -1067,7 +1067,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmax_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false);
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
             }
diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index dd8b44c96b9..5113b65a5c4 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -107,6 +107,20 @@ const POWERPC_WHITELIST: &'static [&'static str] = &["altivec",
 
 const MIPS_WHITELIST: &'static [&'static str] = &["fp64", "msa"];
 
+/// When rustdoc is running, provide a list of all known features so that all their respective
+/// primtives may be documented.
+///
+/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
+/// iterator!
+pub fn all_known_features() -> impl Iterator<Item=&'static str> {
+    ARM_WHITELIST.iter().cloned()
+        .chain(AARCH64_WHITELIST.iter().cloned())
+        .chain(X86_WHITELIST.iter().cloned())
+        .chain(HEXAGON_WHITELIST.iter().cloned())
+        .chain(POWERPC_WHITELIST.iter().cloned())
+        .chain(MIPS_WHITELIST.iter().cloned())
+}
+
 pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
     let arch = if sess.target.target.arch == "x86_64" {
         "x86"
diff --git a/src/librustc_trans_utils/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs
index 267c8d2bd03..47bbd67fb5c 100644
--- a/src/librustc_trans_utils/symbol_names_test.rs
+++ b/src/librustc_trans_utils/symbol_names_test.rs
@@ -15,7 +15,6 @@
 //! paths etc in all kinds of annoying scenarios.
 
 use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
@@ -34,8 +33,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     tcx.dep_graph.with_ignore(|| {
         let mut visitor = SymbolNamesTest { tcx: tcx };
-        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
-        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+        tcx.hir.krate().visit_all_item_likes(&mut visitor);
     })
 }
 
@@ -66,23 +64,16 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
+impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.process_attrs(item.id);
-        intravisit::walk_item(self, item);
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        self.process_attrs(ti.id);
-        intravisit::walk_trait_item(self, ti)
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.process_attrs(trait_item.id);
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        self.process_attrs(ii.id);
-        intravisit::walk_impl_item(self, ii)
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        self.process_attrs(impl_item.id);
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4a685cfddb7..69879bbe85d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -718,6 +718,18 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum
     })?)
 }
 
+fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_item_well_formed(tcx, def_id);
+}
+
+fn check_trait_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_trait_item(tcx, def_id);
+}
+
+fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_impl_item(tcx, def_id);
+}
+
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         typeck_item_bodies,
@@ -725,6 +737,9 @@ pub fn provide(providers: &mut Providers) {
         has_typeck_tables,
         adt_destructor,
         used_trait_imports,
+        check_item_well_formed,
+        check_trait_item_well_formed,
+        check_impl_item_well_formed,
         ..*providers
     };
 }
@@ -2869,7 +2884,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let origin = self.misc(call_span);
                 let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
 
-                // FIXME(#15760) can't use try! here, FromError doesn't default
+                // FIXME(#27336) can't use ? here, Try::from_error doesn't default
                 // to identity so the resulting type is not constrained.
                 match ures {
                     Ok(ok) => {
@@ -2877,19 +2892,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        let result = self.save_and_restore_in_snapshot_flag(|_| {
+                        self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = FulfillmentContext::new();
-                            let ok = ok; // FIXME(#30046)
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
                             fulfill.select_where_possible(self)
-                        });
-
-                        match result {
-                            Ok(()) => { }
-                            Err(_) => return Err(()),
-                        }
+                        }).map_err(|_| ())?;
                     }
                     Err(_) => return Err(()),
                 }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index b94af0a1e00..406ff9463a0 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -26,17 +26,11 @@ use errors::{DiagnosticBuilder, DiagnosticId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
 
-pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    code: ObligationCauseCode<'tcx>,
-}
-
 /// Helper type of a temporary returned by .for_item(...).
 /// Necessary because we can't write the following bound:
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
 struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
-    code: ObligationCauseCode<'gcx>,
     id: ast::NodeId,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
@@ -45,585 +39,597 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
     fn with_fcx<F>(&'tcx mut self, f: F) where
         F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>,
-                          &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec<Ty<'tcx>>
+                         TyCtxt<'b, 'gcx, 'gcx>) -> Vec<Ty<'tcx>>
     {
-        let code = self.code.clone();
         let id = self.id;
         let span = self.span;
         let param_env = self.param_env;
         self.inherited.enter(|inh| {
             let fcx = FnCtxt::new(&inh, param_env, id);
-            let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
-                tcx: fcx.tcx.global_tcx(),
-                code,
-            });
+            let wf_tys = f(&fcx, fcx.tcx.global_tcx());
             fcx.select_all_obligations_or_error();
             fcx.regionck_item(id, span, &wf_tys);
         });
     }
 }
 
-impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
-               -> CheckTypeWellFormedVisitor<'a, 'gcx> {
-        CheckTypeWellFormedVisitor {
-            tcx,
-            code: ObligationCauseCode::MiscObligation
-        }
-    }
-
-    /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
-    /// well-formed, meaning that they do not require any constraints not declared in the struct
-    /// definition itself. For example, this definition would be illegal:
-    ///
-    ///     struct Ref<'a, T> { x: &'a T }
-    ///
-    /// because the type did not declare that `T:'a`.
-    ///
-    /// We do this check as a pre-pass before checking fn bodies because if these constraints are
-    /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
-    /// the types first.
-    fn check_item_well_formed(&mut self, item: &hir::Item) {
-        let tcx = self.tcx;
-        debug!("check_item_well_formed(it.id={}, it.name={})",
-               item.id,
-               tcx.item_path_str(tcx.hir.local_def_id(item.id)));
-
-        match item.node {
-            // Right now we check that every default trait implementation
-            // has an implementation of itself. Basically, a case like:
-            //
-            // `impl Trait for T {}`
-            //
-            // has a requirement of `T: Trait` which was required for default
-            // method implementations. Although this could be improved now that
-            // there's a better infrastructure in place for this, it's being left
-            // for a follow-up work.
-            //
-            // Since there's such a requirement, we need to check *just* positive
-            // implementations, otherwise things like:
-            //
-            // impl !Send for T {}
-            //
-            // won't be allowed unless there's an *explicit* implementation of `Send`
-            // for `T`
-            hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
-                let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
-                                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
-                if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
-                    tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
-                }
-                if polarity == hir::ImplPolarity::Positive {
-                    self.check_impl(item, self_ty, trait_ref);
-                } else {
-                    // FIXME(#27579) what amount of WF checking do we need for neg impls?
-                    if trait_ref.is_some() && !is_auto {
-                        span_err!(tcx.sess, item.span, E0192,
-                                  "negative impls are only allowed for \
-                                   auto traits (e.g., `Send` and `Sync`)")
-                    }
-                }
-            }
-            hir::ItemFn(..) => {
-                self.check_item_fn(item);
-            }
-            hir::ItemStatic(..) => {
-                self.check_item_type(item);
+/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
+/// well-formed, meaning that they do not require any constraints not declared in the struct
+/// definition itself. For example, this definition would be illegal:
+///
+///     struct Ref<'a, T> { x: &'a T }
+///
+/// because the type did not declare that `T:'a`.
+///
+/// We do this check as a pre-pass before checking fn bodies because if these constraints are
+/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
+/// the types first.
+pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let item = tcx.hir.expect_item(node_id);
+
+    debug!("check_item_well_formed(it.id={}, it.name={})",
+            item.id,
+            tcx.item_path_str(def_id));
+
+    match item.node {
+        // Right now we check that every default trait implementation
+        // has an implementation of itself. Basically, a case like:
+        //
+        // `impl Trait for T {}`
+        //
+        // has a requirement of `T: Trait` which was required for default
+        // method implementations. Although this could be improved now that
+        // there's a better infrastructure in place for this, it's being left
+        // for a follow-up work.
+        //
+        // Since there's such a requirement, we need to check *just* positive
+        // implementations, otherwise things like:
+        //
+        // impl !Send for T {}
+        //
+        // won't be allowed unless there's an *explicit* implementation of `Send`
+        // for `T`
+        hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
+            let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
+                                .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
+            if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
+                tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
             }
-            hir::ItemConst(..) => {
-                self.check_item_type(item);
+            if polarity == hir::ImplPolarity::Positive {
+                check_impl(tcx, item, self_ty, trait_ref);
+            } else {
+                // FIXME(#27579) what amount of WF checking do we need for neg impls?
+                if trait_ref.is_some() && !is_auto {
+                    span_err!(tcx.sess, item.span, E0192,
+                                "negative impls are only allowed for \
+                                auto traits (e.g., `Send` and `Sync`)")
+                }
             }
-            hir::ItemStruct(ref struct_def, ref ast_generics) => {
-                self.check_type_defn(item, false, |fcx| {
-                    vec![fcx.non_enum_variant(struct_def)]
-                });
+        }
+        hir::ItemFn(..) => {
+            check_item_fn(tcx, item);
+        }
+        hir::ItemStatic(..) => {
+            check_item_type(tcx, item);
+        }
+        hir::ItemConst(..) => {
+            check_item_type(tcx, item);
+        }
+        hir::ItemStruct(ref struct_def, ref ast_generics) => {
+            check_type_defn(tcx, item, false, |fcx| {
+                vec![fcx.non_enum_variant(struct_def)]
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemUnion(ref struct_def, ref ast_generics) => {
-                self.check_type_defn(item, true, |fcx| {
-                    vec![fcx.non_enum_variant(struct_def)]
-                });
+            check_variances_for_type_defn(tcx, item, ast_generics);
+        }
+        hir::ItemUnion(ref struct_def, ref ast_generics) => {
+            check_type_defn(tcx, item, true, |fcx| {
+                vec![fcx.non_enum_variant(struct_def)]
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemEnum(ref enum_def, ref ast_generics) => {
-                self.check_type_defn(item, true, |fcx| {
-                    fcx.enum_variants(enum_def)
-                });
+            check_variances_for_type_defn(tcx, item, ast_generics);
+        }
+        hir::ItemEnum(ref enum_def, ref ast_generics) => {
+            check_type_defn(tcx, item, true, |fcx| {
+                fcx.enum_variants(enum_def)
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemTrait(..) => {
-                self.check_trait(item);
-            }
-            _ => {}
+            check_variances_for_type_defn(tcx, item, ast_generics);
         }
+        hir::ItemTrait(..) => {
+            check_trait(tcx, item);
+        }
+        _ => {}
     }
+}
 
-    fn check_associated_item(&mut self,
-                             item_id: ast::NodeId,
-                             span: Span,
-                             sig_if_method: Option<&hir::MethodSig>) {
-        let code = self.code.clone();
-        self.for_id(item_id, span).with_fcx(|fcx, this| {
-            let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
-
-            let (mut implied_bounds, self_ty) = match item.container {
-                ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
-                ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
-                                              fcx.tcx.type_of(def_id))
-            };
+pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let trait_item = tcx.hir.expect_trait_item(node_id);
+
+    let method_sig = match trait_item.node {
+        hir::TraitItemKind::Method(ref sig, _) => Some(sig),
+        _ => None
+    };
+    check_associated_item(tcx, trait_item.id, trait_item.span, method_sig);
+}
+
+pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let impl_item = tcx.hir.expect_impl_item(node_id);
+
+    let method_sig = match impl_item.node {
+        hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+        _ => None
+    };
+    check_associated_item(tcx, impl_item.id, impl_item.span, method_sig);
+}
+
+fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            item_id: ast::NodeId,
+                            span: Span,
+                            sig_if_method: Option<&hir::MethodSig>) {
+    let code = ObligationCauseCode::MiscObligation;
+    for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
+        let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
+
+        let (mut implied_bounds, self_ty) = match item.container {
+            ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
+            ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
+                                            fcx.tcx.type_of(def_id))
+        };
 
-            match item.kind {
-                ty::AssociatedKind::Const => {
+        match item.kind {
+            ty::AssociatedKind::Const => {
+                let ty = fcx.tcx.type_of(item.def_id);
+                let ty = fcx.normalize_associated_types_in(span, &ty);
+                fcx.register_wf_obligation(ty, span, code.clone());
+            }
+            ty::AssociatedKind::Method => {
+                reject_shadowing_type_parameters(fcx.tcx, item.def_id);
+                let sig = fcx.tcx.fn_sig(item.def_id);
+                let sig = fcx.normalize_associated_types_in(span, &sig);
+                check_fn_or_method(tcx, fcx, span, sig,
+                                        item.def_id, &mut implied_bounds);
+                let sig_if_method = sig_if_method.expect("bad signature for method");
+                check_method_receiver(fcx, sig_if_method, &item, self_ty);
+            }
+            ty::AssociatedKind::Type => {
+                if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
                     let ty = fcx.normalize_associated_types_in(span, &ty);
                     fcx.register_wf_obligation(ty, span, code.clone());
                 }
-                ty::AssociatedKind::Method => {
-                    reject_shadowing_type_parameters(fcx.tcx, item.def_id);
-                    let sig = fcx.tcx.fn_sig(item.def_id);
-                    let sig = fcx.normalize_associated_types_in(span, &sig);
-                    this.check_fn_or_method(fcx, span, sig,
-                                            item.def_id, &mut implied_bounds);
-                    let sig_if_method = sig_if_method.expect("bad signature for method");
-                    this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
-                }
-                ty::AssociatedKind::Type => {
-                    if item.defaultness.has_value() {
-                        let ty = fcx.tcx.type_of(item.def_id);
-                        let ty = fcx.normalize_associated_types_in(span, &ty);
-                        fcx.register_wf_obligation(ty, span, code.clone());
-                    }
-                }
             }
+        }
 
-            implied_bounds
-        })
-    }
-
-    fn for_item<'tcx>(&self, item: &hir::Item)
-                      -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-        self.for_id(item.id, item.span)
-    }
+        implied_bounds
+    })
+}
 
-    fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
+fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item)
                     -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-        let def_id = self.tcx.hir.local_def_id(id);
-        CheckWfFcxBuilder {
-            inherited: Inherited::build(self.tcx, def_id),
-            code: self.code.clone(),
-            id,
-            span,
-            param_env: self.tcx.param_env(def_id),
-        }
+    for_id(tcx, item.id, item.span)
+}
+
+fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span)
+                -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
+    let def_id = tcx.hir.local_def_id(id);
+    CheckWfFcxBuilder {
+        inherited: Inherited::build(tcx, def_id),
+        id,
+        span,
+        param_env: tcx.param_env(def_id),
     }
+}
 
-    /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-    fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_fields: F)
-        where F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) -> Vec<AdtVariant<'tcx>>
-    {
-        self.for_item(item).with_fcx(|fcx, this| {
-            let variants = lookup_fields(fcx);
-            let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let packed = fcx.tcx.adt_def(def_id).repr.packed();
-
-            for variant in &variants {
-                // For DST, or when drop needs to copy things around, all
-                // intermediate types must be sized.
-                let needs_drop_copy = || {
-                    packed && {
-                        let ty = variant.fields.last().unwrap().ty;
-                        let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(this.tcx)
-                            .unwrap_or_else(|| {
-                                span_bug!(item.span, "inference variables in {:?}", ty)
-                            });
-                        ty.needs_drop(this.tcx, this.tcx.param_env(def_id))
-                    }
-                };
-                let unsized_len = if
-                    all_sized ||
-                    variant.fields.is_empty() ||
-                    needs_drop_copy()
-                {
-                    0
-                } else {
-                    1
-                };
-                for field in &variant.fields[..variant.fields.len() - unsized_len] {
-                    fcx.register_bound(
-                        field.ty,
-                        fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
-                        traits::ObligationCause::new(field.span,
-                                                     fcx.body_id,
-                                                     traits::FieldSized(match item.node.adt_kind() {
-                                                        Some(i) => i,
-                                                        None => bug!(),
-                                                     })));
+/// In a type definition, we check that to ensure that the types of the fields are well-formed.
+fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                item: &hir::Item, all_sized: bool, mut lookup_fields: F)
+    where F: for<'fcx, 'gcx, 'tcx2> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx2>) -> Vec<AdtVariant<'tcx2>>
+{
+    for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
+        let variants = lookup_fields(fcx);
+        let def_id = fcx.tcx.hir.local_def_id(item.id);
+        let packed = fcx.tcx.adt_def(def_id).repr.packed();
+
+        for variant in &variants {
+            // For DST, or when drop needs to copy things around, all
+            // intermediate types must be sized.
+            let needs_drop_copy = || {
+                packed && {
+                    let ty = variant.fields.last().unwrap().ty;
+                    let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx)
+                        .unwrap_or_else(|| {
+                            span_bug!(item.span, "inference variables in {:?}", ty)
+                        });
+                    ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
                 }
+            };
+            let unsized_len = if
+                all_sized ||
+                variant.fields.is_empty() ||
+                needs_drop_copy()
+            {
+                0
+            } else {
+                1
+            };
+            for field in &variant.fields[..variant.fields.len() - unsized_len] {
+                fcx.register_bound(
+                    field.ty,
+                    fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
+                    traits::ObligationCause::new(field.span,
+                                                    fcx.body_id,
+                                                    traits::FieldSized(match item.node.adt_kind() {
+                                                    Some(i) => i,
+                                                    None => bug!(),
+                                                    })));
+            }
 
-                // All field types must be well-formed.
-                for field in &variant.fields {
-                    fcx.register_wf_obligation(field.ty, field.span, this.code.clone())
-                }
+            // All field types must be well-formed.
+            for field in &variant.fields {
+                fcx.register_wf_obligation(field.ty, field.span,
+                    ObligationCauseCode::MiscObligation)
             }
+        }
 
-            self.check_where_clauses(fcx, item.span, def_id);
+        check_where_clauses(tcx, fcx, item.span, def_id);
 
-            vec![] // no implied bounds in a struct def'n
-        });
-    }
+        vec![] // no implied bounds in a struct def'n
+    });
+}
 
-    fn check_trait(&mut self, item: &hir::Item) {
-        let trait_def_id = self.tcx.hir.local_def_id(item.id);
-        self.for_item(item).with_fcx(|fcx, _| {
-            self.check_where_clauses(fcx, item.span, trait_def_id);
-            vec![]
-        });
-    }
+fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    let trait_def_id = tcx.hir.local_def_id(item.id);
+    for_item(tcx, item).with_fcx(|fcx, _| {
+        check_where_clauses(tcx, fcx, item.span, trait_def_id);
+        vec![]
+    });
+}
 
-    fn check_item_fn(&mut self, item: &hir::Item) {
-        self.for_item(item).with_fcx(|fcx, this| {
-            let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let sig = fcx.tcx.fn_sig(def_id);
-            let sig = fcx.normalize_associated_types_in(item.span, &sig);
-            let mut implied_bounds = vec![];
-            this.check_fn_or_method(fcx, item.span, sig,
-                                    def_id, &mut implied_bounds);
-            implied_bounds
-        })
-    }
+fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    for_item(tcx, item).with_fcx(|fcx, tcx| {
+        let def_id = fcx.tcx.hir.local_def_id(item.id);
+        let sig = fcx.tcx.fn_sig(def_id);
+        let sig = fcx.normalize_associated_types_in(item.span, &sig);
+        let mut implied_bounds = vec![];
+        check_fn_or_method(tcx, fcx, item.span, sig,
+                                def_id, &mut implied_bounds);
+        implied_bounds
+    })
+}
 
-    fn check_item_type(&mut self,
-                       item: &hir::Item)
-    {
-        debug!("check_item_type: {:?}", item);
+fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    item: &hir::Item)
+{
+    debug!("check_item_type: {:?}", item);
 
-        self.for_item(item).with_fcx(|fcx, this| {
-            let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
-            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
+    for_item(tcx, item).with_fcx(|fcx, _this| {
+        let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
+        let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
 
-            fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
+        fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation);
 
-            vec![] // no implied bounds in a const etc
-        });
-    }
+        vec![] // no implied bounds in a const etc
+    });
+}
 
-    fn check_impl(&mut self,
-                  item: &hir::Item,
-                  ast_self_ty: &hir::Ty,
-                  ast_trait_ref: &Option<hir::TraitRef>)
-    {
-        debug!("check_impl: {:?}", item);
-
-        self.for_item(item).with_fcx(|fcx, this| {
-            let item_def_id = fcx.tcx.hir.local_def_id(item.id);
-
-            match *ast_trait_ref {
-                Some(ref ast_trait_ref) => {
-                    let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
-                    let trait_ref =
-                        fcx.normalize_associated_types_in(
-                            ast_trait_ref.path.span, &trait_ref);
-                    let obligations =
-                        ty::wf::trait_obligations(fcx,
-                                                  fcx.param_env,
-                                                  fcx.body_id,
-                                                  &trait_ref,
-                                                  ast_trait_ref.path.span);
-                    for obligation in obligations {
-                        fcx.register_predicate(obligation);
-                    }
-                }
-                None => {
-                    let self_ty = fcx.tcx.type_of(item_def_id);
-                    let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
-                    fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
+fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                item: &hir::Item,
+                ast_self_ty: &hir::Ty,
+                ast_trait_ref: &Option<hir::TraitRef>)
+{
+    debug!("check_impl: {:?}", item);
+
+    for_item(tcx, item).with_fcx(|fcx, tcx| {
+        let item_def_id = fcx.tcx.hir.local_def_id(item.id);
+
+        match *ast_trait_ref {
+            Some(ref ast_trait_ref) => {
+                let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
+                let trait_ref =
+                    fcx.normalize_associated_types_in(
+                        ast_trait_ref.path.span, &trait_ref);
+                let obligations =
+                    ty::wf::trait_obligations(fcx,
+                                                fcx.param_env,
+                                                fcx.body_id,
+                                                &trait_ref,
+                                                ast_trait_ref.path.span);
+                for obligation in obligations {
+                    fcx.register_predicate(obligation);
                 }
             }
+            None => {
+                let self_ty = fcx.tcx.type_of(item_def_id);
+                let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
+                fcx.register_wf_obligation(self_ty, ast_self_ty.span,
+                    ObligationCauseCode::MiscObligation);
+            }
+        }
 
-            this.check_where_clauses(fcx, item.span, item_def_id);
+        check_where_clauses(tcx, fcx, item.span, item_def_id);
 
-            fcx.impl_implied_bounds(item_def_id, item.span)
-        });
-    }
+        fcx.impl_implied_bounds(item_def_id, item.span)
+    });
+}
 
-    /// Checks where clauses and inline bounds that are declared on def_id.
-    fn check_where_clauses<'fcx, 'tcx>(&mut self,
-                                       fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                       span: Span,
-                                       def_id: DefId) {
-        use ty::subst::Subst;
-        use rustc::ty::TypeFoldable;
-
-        let mut predicates = fcx.tcx.predicates_of(def_id);
-        let mut substituted_predicates = Vec::new();
-
-        let generics = self.tcx.generics_of(def_id);
-        let is_our_default = |def: &ty::TypeParameterDef|
-                                def.has_default && def.index >= generics.parent_count() as u32;
-
-        // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
-        // For example this forbids the declaration:
-        // struct Foo<T = Vec<[u32]>> { .. }
-        // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
-        for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
-            let ty = fcx.tcx.type_of(d);
-            // ignore dependent defaults -- that is, where the default of one type
-            // parameter includes another (e.g., <T, U = T>). In those cases, we can't
-            // be sure if it will error or not as user might always specify the other.
-            if !ty.needs_subst() {
-                fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
-            }
+/// Checks where clauses and inline bounds that are declared on def_id.
+fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                                    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                    span: Span,
+                                    def_id: DefId) {
+    use ty::subst::Subst;
+    use rustc::ty::TypeFoldable;
+
+    let mut predicates = fcx.tcx.predicates_of(def_id);
+    let mut substituted_predicates = Vec::new();
+
+    let generics = tcx.generics_of(def_id);
+    let is_our_default = |def: &ty::TypeParameterDef|
+                            def.has_default && def.index >= generics.parent_count() as u32;
+
+    // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
+    // For example this forbids the declaration:
+    // struct Foo<T = Vec<[u32]>> { .. }
+    // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
+    for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
+        let ty = fcx.tcx.type_of(d);
+        // ignore dependent defaults -- that is, where the default of one type
+        // parameter includes another (e.g., <T, U = T>). In those cases, we can't
+        // be sure if it will error or not as user might always specify the other.
+        if !ty.needs_subst() {
+            fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
+                ObligationCauseCode::MiscObligation);
         }
+    }
 
-        // Check that trait predicates are WF when params are substituted by their defaults.
-        // We don't want to overly constrain the predicates that may be written but we want to
-        // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
-        // Therefore we check if a predicate which contains a single type param
-        // with a concrete default is WF with that default substituted.
-        // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
-        //
-        // First we build the defaulted substitution.
-        let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
-                // All regions are identity.
-                fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
-            }, |def, _| {
-                // If the param has a default,
-                if is_our_default(def) {
-                    let default_ty = fcx.tcx.type_of(def.def_id);
-                    // and it's not a dependent default
-                    if !default_ty.needs_subst() {
-                        // then substitute with the default.
-                        return default_ty;
-                    }
+    // Check that trait predicates are WF when params are substituted by their defaults.
+    // We don't want to overly constrain the predicates that may be written but we want to
+    // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
+    // Therefore we check if a predicate which contains a single type param
+    // with a concrete default is WF with that default substituted.
+    // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
+    //
+    // First we build the defaulted substitution.
+    let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
+            // All regions are identity.
+            fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
+        }, |def, _| {
+            // If the param has a default,
+            if is_our_default(def) {
+                let default_ty = fcx.tcx.type_of(def.def_id);
+                // and it's not a dependent default
+                if !default_ty.needs_subst() {
+                    // then substitute with the default.
+                    return default_ty;
                 }
-                // Mark unwanted params as err.
-                fcx.tcx.types.err
-            });
-        // Now we build the substituted predicates.
-        for &pred in predicates.predicates.iter() {
-            struct CountParams { params: FxHashSet<u32> }
-            impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
-                fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-                    match t.sty {
-                        ty::TyParam(p) => {
-                            self.params.insert(p.idx);
-                            t.super_visit_with(self)
-                        }
-                        _ => t.super_visit_with(self)
+            }
+            // Mark unwanted params as err.
+            fcx.tcx.types.err
+        });
+    // Now we build the substituted predicates.
+    for &pred in predicates.predicates.iter() {
+        struct CountParams { params: FxHashSet<u32> }
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                match t.sty {
+                    ty::TyParam(p) => {
+                        self.params.insert(p.idx);
+                        t.super_visit_with(self)
                     }
+                    _ => t.super_visit_with(self)
                 }
             }
-            let mut param_count = CountParams { params: FxHashSet() };
-            pred.visit_with(&mut param_count);
-            let substituted_pred = pred.subst(fcx.tcx, substs);
-            // Don't check non-defaulted params, dependent defaults or preds with multiple params.
-            if substituted_pred.references_error() || param_count.params.len() > 1 {
-                continue;
-            }
-            // Avoid duplication of predicates that contain no parameters, for example.
-            if !predicates.predicates.contains(&substituted_pred) {
-                substituted_predicates.push(substituted_pred);
-            }
         }
-
-        predicates.predicates.extend(substituted_predicates);
-        let predicates = predicates.instantiate_identity(fcx.tcx);
-        let predicates = fcx.normalize_associated_types_in(span, &predicates);
-
-        let obligations =
-            predicates.predicates
-                      .iter()
-                      .flat_map(|p| ty::wf::predicate_obligations(fcx,
-                                                                  fcx.param_env,
-                                                                  fcx.body_id,
-                                                                  p,
-                                                                  span));
-
-        for obligation in obligations {
-            fcx.register_predicate(obligation);
+        let mut param_count = CountParams { params: FxHashSet() };
+        pred.visit_with(&mut param_count);
+        let substituted_pred = pred.subst(fcx.tcx, substs);
+        // Don't check non-defaulted params, dependent defaults or preds with multiple params.
+        if substituted_pred.references_error() || param_count.params.len() > 1 {
+            continue;
+        }
+        // Avoid duplication of predicates that contain no parameters, for example.
+        if !predicates.predicates.contains(&substituted_pred) {
+            substituted_predicates.push(substituted_pred);
         }
     }
 
-    fn check_fn_or_method<'fcx, 'tcx>(&mut self,
-                                      fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                      span: Span,
-                                      sig: ty::PolyFnSig<'tcx>,
-                                      def_id: DefId,
-                                      implied_bounds: &mut Vec<Ty<'tcx>>)
-    {
-        let sig = fcx.normalize_associated_types_in(span, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
-
-        for input_ty in sig.inputs() {
-            fcx.register_wf_obligation(&input_ty, span, self.code.clone());
-        }
-        implied_bounds.extend(sig.inputs());
+    predicates.predicates.extend(substituted_predicates);
+    let predicates = predicates.instantiate_identity(fcx.tcx);
+    let predicates = fcx.normalize_associated_types_in(span, &predicates);
+
+    let obligations =
+        predicates.predicates
+                    .iter()
+                    .flat_map(|p| ty::wf::predicate_obligations(fcx,
+                                                                fcx.param_env,
+                                                                fcx.body_id,
+                                                                p,
+                                                                span));
+
+    for obligation in obligations {
+        fcx.register_predicate(obligation);
+    }
+}
 
-        fcx.register_wf_obligation(sig.output(), span, self.code.clone());
+fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                                    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                    span: Span,
+                                    sig: ty::PolyFnSig<'tcx>,
+                                    def_id: DefId,
+                                    implied_bounds: &mut Vec<Ty<'tcx>>)
+{
+    let sig = fcx.normalize_associated_types_in(span, &sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
+
+    for input_ty in sig.inputs() {
+        fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation);
+    }
+    implied_bounds.extend(sig.inputs());
 
-        // FIXME(#25759) return types should not be implied bounds
-        implied_bounds.push(sig.output());
+    fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation);
 
-        self.check_where_clauses(fcx, span, def_id);
-    }
+    // FIXME(#25759) return types should not be implied bounds
+    implied_bounds.push(sig.output());
 
-    fn check_method_receiver<'fcx, 'tcx>(&mut self,
-                                         fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                         method_sig: &hir::MethodSig,
-                                         method: &ty::AssociatedItem,
-                                         self_ty: Ty<'tcx>)
-    {
-        // check that the method has a valid receiver type, given the type `Self`
-        debug!("check_method_receiver({:?}, self_ty={:?})",
-               method, self_ty);
+    check_where_clauses(tcx, fcx, span, def_id);
+}
 
-        if !method.method_has_self_argument {
-            return;
-        }
+fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                           method_sig: &hir::MethodSig,
+                                           method: &ty::AssociatedItem,
+                                           self_ty: Ty<'tcx>)
+{
+    // check that the method has a valid receiver type, given the type `Self`
+    debug!("check_method_receiver({:?}, self_ty={:?})",
+            method, self_ty);
+
+    if !method.method_has_self_argument {
+        return;
+    }
 
-        let span = method_sig.decl.inputs[0].span;
+    let span = method_sig.decl.inputs[0].span;
 
-        let sig = fcx.tcx.fn_sig(method.def_id);
-        let sig = fcx.normalize_associated_types_in(span, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig);
+    let sig = fcx.tcx.fn_sig(method.def_id);
+    let sig = fcx.normalize_associated_types_in(span, &sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig);
 
-        debug!("check_method_receiver: sig={:?}", sig);
+    debug!("check_method_receiver: sig={:?}", sig);
 
-        let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
-        let self_ty = fcx.tcx.liberate_late_bound_regions(
-            method.def_id,
-            &ty::Binder(self_ty)
-        );
+    let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
+    let self_ty = fcx.tcx.liberate_late_bound_regions(
+        method.def_id,
+        &ty::Binder(self_ty)
+    );
 
-        let self_arg_ty = sig.inputs()[0];
+    let self_arg_ty = sig.inputs()[0];
 
-        let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
-        let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
-        let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
-            method.def_id,
-            &ty::Binder(self_arg_ty)
-        );
+    let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
+    let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
+    let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
+        method.def_id,
+        &ty::Binder(self_arg_ty)
+    );
 
-        let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
+    let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
 
-        loop {
-            if let Some((potential_self_ty, _)) = autoderef.next() {
-                debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
-                    potential_self_ty, self_ty);
+    loop {
+        if let Some((potential_self_ty, _)) = autoderef.next() {
+            debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
+                potential_self_ty, self_ty);
 
-                if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
-                    autoderef.finalize();
-                    if let Some(mut err) = fcx.demand_eqtype_with_origin(
-                        &cause, self_ty, potential_self_ty) {
-                        err.emit();
-                    }
-                    break
+            if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
+                autoderef.finalize();
+                if let Some(mut err) = fcx.demand_eqtype_with_origin(
+                    &cause, self_ty, potential_self_ty) {
+                    err.emit();
                 }
-            } else {
-                fcx.tcx.sess.diagnostic().mut_span_err(
-                    span, &format!("invalid `self` type: {:?}", self_arg_ty))
-                .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
-                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                .code(DiagnosticId::Error("E0307".into()))
-                .emit();
-                return
+                break
             }
+        } else {
+            fcx.tcx.sess.diagnostic().mut_span_err(
+                span, &format!("invalid `self` type: {:?}", self_arg_ty))
+            .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
+            .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+            .code(DiagnosticId::Error("E0307".into()))
+            .emit();
+            return
         }
+    }
 
-        let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
-        let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
-
-        if !fcx.tcx.features().arbitrary_self_types {
-            match self_kind {
-                ExplicitSelf::ByValue |
-                ExplicitSelf::ByReference(_, _) |
-                ExplicitSelf::ByBox => (),
-
-                ExplicitSelf::ByRawPointer(_) => {
-                    feature_gate::feature_err(
-                        &fcx.tcx.sess.parse_sess,
-                        "arbitrary_self_types",
-                        span,
-                        GateIssue::Language,
-                        "raw pointer `self` is unstable")
-                    .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                    .emit();
-                }
+    let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
+    let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
+
+    if !fcx.tcx.features().arbitrary_self_types {
+        match self_kind {
+            ExplicitSelf::ByValue |
+            ExplicitSelf::ByReference(_, _) |
+            ExplicitSelf::ByBox => (),
+
+            ExplicitSelf::ByRawPointer(_) => {
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,
+                    "raw pointer `self` is unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
+            }
 
-                ExplicitSelf::Other => {
-                    feature_gate::feature_err(
-                        &fcx.tcx.sess.parse_sess,
-                        "arbitrary_self_types",
-                        span,
-                        GateIssue::Language,"arbitrary `self` types are unstable")
-                    .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                    .emit();
-                }
+            ExplicitSelf::Other => {
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,"arbitrary `self` types are unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
             }
         }
     }
+}
 
-    fn check_variances_for_type_defn(&self,
-                                     item: &hir::Item,
-                                     ast_generics: &hir::Generics)
-    {
-        let item_def_id = self.tcx.hir.local_def_id(item.id);
-        let ty = self.tcx.type_of(item_def_id);
-        if self.tcx.has_error_field(ty) {
-            return;
-        }
-
-        let ty_predicates = self.tcx.predicates_of(item_def_id);
-        assert_eq!(ty_predicates.parent, None);
-        let variances = self.tcx.variances_of(item_def_id);
+fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                    item: &hir::Item,
+                                    ast_generics: &hir::Generics)
+{
+    let item_def_id = tcx.hir.local_def_id(item.id);
+    let ty = tcx.type_of(item_def_id);
+    if tcx.has_error_field(ty) {
+        return;
+    }
 
-        let mut constrained_parameters: FxHashSet<_> =
-            variances.iter().enumerate()
-                     .filter(|&(_, &variance)| variance != ty::Bivariant)
-                     .map(|(index, _)| Parameter(index as u32))
-                     .collect();
+    let ty_predicates = tcx.predicates_of(item_def_id);
+    assert_eq!(ty_predicates.parent, None);
+    let variances = tcx.variances_of(item_def_id);
 
-        identify_constrained_type_params(self.tcx,
-                                         ty_predicates.predicates.as_slice(),
-                                         None,
-                                         &mut constrained_parameters);
+    let mut constrained_parameters: FxHashSet<_> =
+        variances.iter().enumerate()
+                    .filter(|&(_, &variance)| variance != ty::Bivariant)
+                    .map(|(index, _)| Parameter(index as u32))
+                    .collect();
 
-        for (index, _) in variances.iter().enumerate() {
-            if constrained_parameters.contains(&Parameter(index as u32)) {
-                continue;
-            }
+    identify_constrained_type_params(tcx,
+                                        ty_predicates.predicates.as_slice(),
+                                        None,
+                                        &mut constrained_parameters);
 
-            let (span, name) = match ast_generics.params[index] {
-                hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
-                hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
-            };
-            self.report_bivariance(span, name);
+    for (index, _) in variances.iter().enumerate() {
+        if constrained_parameters.contains(&Parameter(index as u32)) {
+            continue;
         }
+
+        let (span, name) = match ast_generics.params[index] {
+            hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
+            hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
+        };
+        report_bivariance(tcx, span, name);
     }
+}
 
-    fn report_bivariance(&self,
-                         span: Span,
-                         param_name: ast::Name)
-    {
-        let mut err = error_392(self.tcx, span, param_name);
-
-        let suggested_marker_id = self.tcx.lang_items().phantom_data();
-        match suggested_marker_id {
-            Some(def_id) => {
-                err.help(
-                    &format!("consider removing `{}` or using a marker such as `{}`",
-                             param_name,
-                             self.tcx.item_path_str(def_id)));
-            }
-            None => {
-                // no lang items, no help!
-            }
+fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        span: Span,
+                        param_name: ast::Name)
+{
+    let mut err = error_392(tcx, span, param_name);
+
+    let suggested_marker_id = tcx.lang_items().phantom_data();
+    match suggested_marker_id {
+        Some(def_id) => {
+            err.help(
+                &format!("consider removing `{}` or using a marker such as `{}`",
+                            param_name,
+                            tcx.item_path_str(def_id)));
+        }
+        None => {
+            // no lang items, no help!
         }
-        err.emit();
     }
+    err.emit();
 }
 
 fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
@@ -648,6 +654,19 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
     }
 }
 
+pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
+               -> CheckTypeWellFormedVisitor<'a, 'gcx> {
+        CheckTypeWellFormedVisitor {
+            tcx,
+        }
+    }
+}
+
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
         NestedVisitorMap::None
@@ -655,27 +674,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
 
     fn visit_item(&mut self, i: &hir::Item) {
         debug!("visit_item: {:?}", i);
-        self.check_item_well_formed(i);
+        let def_id = self.tcx.hir.local_def_id(i.id);
+        ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_item(self, i);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
-        let method_sig = match trait_item.node {
-            hir::TraitItemKind::Method(ref sig, _) => Some(sig),
-            _ => None
-        };
-        self.check_associated_item(trait_item.id, trait_item.span, method_sig);
+        let def_id = self.tcx.hir.local_def_id(trait_item.id);
+        ty::maps::queries::check_trait_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_trait_item(self, trait_item)
     }
 
     fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
-        let method_sig = match impl_item.node {
-            hir::ImplItemKind::Method(ref sig, _) => Some(sig),
-            _ => None
-        };
-        self.check_associated_item(impl_item.id, impl_item.span, method_sig);
+        let def_id = self.tcx.hir.local_def_id(impl_item.id);
+        ty::maps::queries::check_impl_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 5cac2d1bbe7..c228f54217d 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -138,7 +138,7 @@ impl Cfg {
 
     /// Renders the configuration for human display, as a short HTML description.
     pub(crate) fn render_short_html(&self) -> String {
-        let mut msg = Html(self).to_string();
+        let mut msg = ShortHtml(self).to_string();
         if self.should_capitalize_first_letter() {
             if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
                 msg[i .. i+1].make_ascii_uppercase();
@@ -149,7 +149,13 @@ impl Cfg {
 
     /// Renders the configuration for long display, as a long HTML description.
     pub(crate) fn render_long_html(&self) -> String {
-        let mut msg = format!("This is supported on <strong>{}</strong>", Html(self));
+        let on = if self.should_use_with_in_description() {
+            "with"
+        } else {
+            "on"
+        };
+
+        let mut msg = format!("This is supported {} <strong>{}</strong>", on, Html(self));
         if self.should_append_only_to_description() {
             msg.push_str(" only");
         }
@@ -180,6 +186,13 @@ impl Cfg {
             }
         }
     }
+
+    fn should_use_with_in_description(&self) -> bool {
+        match *self {
+            Cfg::Cfg(ref name, _) if name == &"target_feature" => true,
+            _ => false,
+        }
+    }
 }
 
 impl ops::Not for Cfg {
@@ -376,6 +389,8 @@ impl<'a> fmt::Display for Html<'a> {
                     },
                     ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
                     ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
+                    ("target_feature", Some(feat)) =>
+                        return write!(fmt, "target feature <code>{}</code>", feat),
                     _ => "",
                 };
                 if !human_readable.is_empty() {
@@ -390,6 +405,19 @@ impl<'a> fmt::Display for Html<'a> {
     }
 }
 
+struct ShortHtml<'a>(&'a Cfg);
+
+impl<'a> fmt::Display for ShortHtml<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match *self.0 {
+            Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => {
+                write!(fmt, "<code>{}</code>", vendor)
+            },
+            ref cfg => write!(fmt, "{}", Html(cfg)),
+        }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::Cfg;
@@ -824,6 +852,10 @@ mod test {
                 ).render_short_html(),
                 "(Debug-assertions enabled or Windows) and Unix"
             );
+            assert_eq!(
+                name_value_cfg("target_feature", "sse2").render_short_html(),
+                "<code>sse2</code>"
+            );
         })
     }
 
@@ -898,6 +930,10 @@ mod test {
                 "This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
                 </strong> only."
             );
+            assert_eq!(
+                name_value_cfg("target_feature", "sse2").render_long_html(),
+                "This is supported with <strong>target feature <code>sse2</code></strong> only."
+            );
         })
     }
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 904c24815cb..1a42b02140c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -828,6 +828,19 @@ impl Attributes {
             })
         }).collect();
 
+        // treat #[target_feature(enable = "feat")] attributes as if they were
+        // #[doc(cfg(target_feature = "feat"))] attributes as well
+        for attr in attrs.lists("target_feature") {
+            if attr.check_name("enable") {
+                if let Some(feat) = attr.value_str() {
+                    let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
+                    if let Ok(feat_cfg) = Cfg::parse(&meta) {
+                        cfg &= feat_cfg;
+                    }
+                }
+            }
+        }
+
         Attributes {
             doc_strings,
             other_attrs,
@@ -929,7 +942,7 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
                       select the {}",
                       disambig1, kind1, disambig2,
                       kind2))
-             .emit();
+      .emit();
 }
 
 /// Given an enum variant's def, return the def of its enum and the associated fragment
@@ -1074,6 +1087,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
     }
 }
 
+#[derive(Debug)]
 enum PathKind {
     /// can be either value or type, not a macro
     Unknown,
@@ -1082,7 +1096,7 @@ enum PathKind {
     /// values, functions, consts, statics, everything in the value namespace
     Value,
     /// types, traits, everything in the type namespace
-    Type
+    Type,
 }
 
 impl Clean<Attributes> for [ast::Attribute] {
@@ -1091,12 +1105,13 @@ impl Clean<Attributes> for [ast::Attribute] {
 
         if UnstableFeatures::from_environment().is_nightly_build() {
             let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
-            for link in markdown_links(&dox) {
+            for ori_link in markdown_links(&dox) {
                 // bail early for real links
-                if link.contains('/') {
+                if ori_link.contains('/') {
                     continue;
                 }
-                let (def, fragment)  = {
+                let link = ori_link.replace("`", "");
+                let (def, fragment) = {
                     let mut kind = PathKind::Unknown;
                     let path_str = if let Some(prefix) =
                         ["struct@", "enum@", "type@",
@@ -1132,7 +1147,6 @@ impl Clean<Attributes> for [ast::Attribute] {
                         continue;
                     }
 
-
                     match kind {
                         PathKind::Value => {
                             if let Ok(def) = resolve(cx, path_str, true) {
@@ -1206,9 +1220,8 @@ impl Clean<Attributes> for [ast::Attribute] {
                     }
                 };
 
-
                 let id = register_def(cx, def);
-                attrs.links.push((link, id, fragment));
+                attrs.links.push((ori_link, id, fragment));
             }
 
             cx.sess().abort_if_errors();
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5e55353a26e..c09bd4cc84a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -27,6 +27,7 @@
 
 #![allow(non_camel_case_types)]
 
+use rustc::session;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
@@ -232,14 +233,14 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
 /// Make headings links with anchor ids and build up TOC.
 struct LinkReplacer<'a, 'b, I: Iterator<Item = Event<'a>>> {
     inner: I,
-    links: &'b [(String, String)]
+    links: &'b [(String, String)],
 }
 
 impl<'a, 'b, I: Iterator<Item = Event<'a>>> LinkReplacer<'a, 'b, I> {
     fn new(iter: I, links: &'b [(String, String)]) -> Self {
         LinkReplacer {
             inner: iter,
-            links
+            links,
         }
     }
 }
@@ -434,7 +435,8 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Footnotes<'a, I> {
     }
 }
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
+                          sess: Option<&session::Session>) {
     tests.set_position(position);
 
     let mut parser = Parser::new(doc);
@@ -484,6 +486,9 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                                    line, filename, block_info.allow_fail);
                     prev_offset = offset;
                 } else {
+                    if let Some(ref sess) = sess {
+                        sess.span_warn(position, "invalid start of a new code block");
+                    }
                     break;
                 }
             }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 0f107457d2b..3a55b279b5c 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -152,7 +152,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(PathBuf::from(input)),
                                        linker);
-    find_testable_code(&input_str, &mut collector, DUMMY_SP);
+    find_testable_code(&input_str, &mut collector, DUMMY_SP, None);
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests,
                        testing::Options::new().display_output(display_warnings));
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 117b21d4758..3ce8bd4ebb4 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -416,6 +416,7 @@ fn partition_source(s: &str) -> (String, String) {
         let trimline = line.trim();
         let header = trimline.is_whitespace() ||
             trimline.starts_with("#![") ||
+            trimline.starts_with("#[macro_use] extern crate") ||
             trimline.starts_with("extern crate");
         if !header || after_header {
             after_header = true;
@@ -645,8 +646,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
         // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us
         if let Some(doc) = attrs.collapsed_doc_value() {
-            markdown::find_testable_code(&doc, self.collector,
-                                         attrs.span.unwrap_or(DUMMY_SP));
+            markdown::find_testable_code(&doc,
+                                         self.collector,
+                                         attrs.span.unwrap_or(DUMMY_SP),
+                                         Some(self.sess));
         }
 
         nested(self);
@@ -826,6 +829,24 @@ assert_eq!(2+2, 4);
     }
 
     #[test]
+    fn make_test_manual_extern_crate_with_macro_use() {
+        let opts = TestOptions::default();
+        let input =
+"#[macro_use] extern crate asdf;
+use asdf::qwop;
+assert_eq!(2+2, 4);";
+        let expected =
+"#![allow(unused)]
+#[macro_use] extern crate asdf;
+fn main() {
+use asdf::qwop;
+assert_eq!(2+2, 4);
+}".to_string();
+        let output = make_test(input, Some("asdf"), false, &opts);
+        assert_eq!(output, (expected, 2));
+    }
+
+    #[test]
     fn make_test_opts_attrs() {
         //if you supplied some doctest attributes with #![doc(test(attr(...)))], it will use those
         //instead of the stock #![allow(unused)]
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 0837ff91c14..6472edb0aa7 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -52,6 +52,7 @@ pub use core::ascii::{EscapeDefault, escape_default};
 ///
 /// [combining character]: https://en.wikipedia.org/wiki/Combining_character
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
 pub trait AsciiExt {
     /// Container type for copied ASCII characters.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -84,6 +85,7 @@ pub trait AsciiExt {
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_uppercase(&self) -> Self::Owned;
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -104,6 +106,7 @@ pub trait AsciiExt {
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_lowercase(&self) -> Self::Owned;
 
     /// Checks that two values are an ASCII case-insensitive match.
@@ -162,6 +165,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII uppercase character:
@@ -174,6 +178,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII lowercase character:
@@ -186,6 +191,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII alphanumeric character:
@@ -199,6 +205,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII decimal digit:
@@ -211,6 +218,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII hexadecimal digit:
@@ -224,6 +232,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII punctuation character:
@@ -241,6 +250,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII graphic character:
@@ -253,6 +263,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII whitespace character:
@@ -282,6 +293,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII control character:
@@ -294,6 +306,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
@@ -354,6 +367,7 @@ macro_rules! delegating_ascii_ctype_methods {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for u8 {
     type Owned = u8;
 
@@ -362,6 +376,7 @@ impl AsciiExt for u8 {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for char {
     type Owned = char;
 
@@ -370,6 +385,7 @@ impl AsciiExt for char {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
 
@@ -427,6 +443,7 @@ impl AsciiExt for [u8] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for str {
     type Owned = String;
 
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index f8dbe193fed..79bb6af168f 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -56,7 +56,6 @@ use any::TypeId;
 use borrow::Cow;
 use cell;
 use char;
-use convert;
 use core::array;
 use fmt::{self, Debug, Display};
 use mem::transmute;
@@ -371,14 +370,6 @@ impl Error for char::ParseCharError {
     }
 }
 
-#[unstable(feature = "try_from", issue = "33417")]
-impl Error for convert::Infallible {
-    fn description(&self) -> &str {
-        match *self {
-        }
-    }
-}
-
 // copied from any.rs
 impl Error + 'static {
     /// Returns true if the boxed type is the same as `T`
diff --git a/src/libstd/num.rs b/src/libstd/num.rs
index a2c133954a3..33d70538522 100644
--- a/src/libstd/num.rs
+++ b/src/libstd/num.rs
@@ -169,7 +169,6 @@ mod tests {
 
     macro_rules! test_checked_next_power_of_two {
         ($test_name:ident, $T:ident) => (
-            #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119)
             fn $test_name() {
                 #![test]
                 assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index f1ab9c47609..afa8e3e1369 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -10,7 +10,6 @@
 
 #![unstable(feature = "process_internals", issue = "0")]
 
-use ascii::AsciiExt;
 use collections::BTreeMap;
 use env::split_paths;
 use env;
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 9fff8b91f96..78b2bb5fe6e 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -27,7 +27,6 @@
 
 use core::str::next_code_point;
 
-use ascii::*;
 use borrow::Cow;
 use char;
 use fmt;
@@ -871,24 +870,22 @@ impl Hash for Wtf8 {
     }
 }
 
-impl AsciiExt for Wtf8 {
-    type Owned = Wtf8Buf;
-
-    fn is_ascii(&self) -> bool {
+impl Wtf8 {
+    pub fn is_ascii(&self) -> bool {
         self.bytes.is_ascii()
     }
-    fn to_ascii_uppercase(&self) -> Wtf8Buf {
+    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
         Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
     }
-    fn to_ascii_lowercase(&self) -> Wtf8Buf {
+    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
         Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
     }
-    fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
+    pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
         self.bytes.eq_ignore_ascii_case(&other.bytes)
     }
 
-    fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
-    fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
+    pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
+    pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
 }
 
 #[cfg(test)]
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index f7e5d40b524..202dc03eaa4 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -298,7 +298,6 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
     debug!("parse_str_lit: given {}", escape_default(lit));
     let mut res = String::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
@@ -503,7 +502,6 @@ pub fn byte_lit(lit: &str) -> (u8, usize) {
 pub fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
     let mut res = Vec::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 9edfa767d31..5264b627e96 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -628,8 +628,15 @@ fn path_node(ids: Vec<Ident>) -> ast::Path {
 }
 
 fn path_name_i(idents: &[Ident]) -> String {
-    // FIXME: Bad copies (#2543 -- same for everything else that says "bad")
-    idents.iter().map(|i| i.to_string()).collect::<Vec<String>>().join("::")
+    let mut path_name = "".to_string();
+    let mut idents_iter = idents.iter().peekable();
+    while let Some(ident) = idents_iter.next() {
+        path_name.push_str(&ident.name.as_str());
+        if let Some(_) = idents_iter.peek() {
+            path_name.push_str("::")
+        }
+    }
+    path_name
 }
 
 fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
@@ -682,7 +689,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // gensym information.
 
     let span = ignored_span(cx, test.span);
-    let path = test.path.clone();
     let ecx = &cx.ext_cx;
     let self_id = ecx.ident_of("self");
     let test_id = ecx.ident_of("test");
@@ -694,10 +700,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // creates $name: $expr
     let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
 
-    debug!("encoding {}", path_name_i(&path[..]));
-
     // path to the #[test] function: "foo::bar::baz"
-    let path_string = path_name_i(&path[..]);
+    let path_string = path_name_i(&test.path[..]);
+
+    debug!("encoding {}", path_string);
+
     let name_expr = ecx.expr_str(span, Symbol::intern(&path_string));
 
     // self::test::StaticTestName($name_expr)
@@ -744,7 +751,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             diag.bug("expected to find top-level re-export name, but found None");
         }
     };
-    visible_path.extend(path);
+    visible_path.extend_from_slice(&test.path[..]);
 
     // Rather than directly give the test function to the test
     // harness, we create a wrapper like one of the following:
diff --git a/src/stdsimd b/src/stdsimd
-Subproject ab9356f2af650815d339d77306f0d09c44d531a
+Subproject bcb720e55861c38db47f2ebdf26b7198338cb39
diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs
index 707531bf376..367d509cadf 100644
--- a/src/test/codegen/abi-main-signature-16bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs
@@ -19,6 +19,7 @@
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
+// ignore-powerpc64
 // ignore-s390x
 // ignore-sparc
 // ignore-wasm32
diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs
index 9bfe47d0a1f..d6dd3f356b5 100644
--- a/src/test/codegen/fastcall-inreg.rs
+++ b/src/test/codegen/fastcall-inreg.rs
@@ -23,6 +23,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs
index 94b69a6cab5..6b79e79fa00 100644
--- a/src/test/codegen/global_asm.rs
+++ b/src/test/codegen/global_asm.rs
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs
index c3688077f22..3f73a1cabbf 100644
--- a/src/test/codegen/global_asm_include.rs
+++ b/src/test/codegen/global_asm_include.rs
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs
index 3b8fe43fa04..3e118a50d45 100644
--- a/src/test/codegen/global_asm_x2.rs
+++ b/src/test/codegen/global_asm_x2.rs
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs
index 655e67cf7ee..2eeed2b788c 100644
--- a/src/test/codegen/repr-transparent-aggregates-1.rs
+++ b/src/test/codegen/repr-transparent-aggregates-1.rs
@@ -14,6 +14,7 @@
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
+// ignore-powerpc64
 // See repr-transparent.rs
 
 #![crate_type="lib"]
diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk
index d9103e19927..af1707de6c0 100644
--- a/src/test/run-make/tools.mk
+++ b/src/test/run-make/tools.mk
@@ -9,7 +9,7 @@ RUSTC_ORIGINAL := $(RUSTC)
 BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)'
 BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)'
 RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS)
-RUSTDOC := $(BARE_RUSTDOC)
+RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR)
 ifdef RUSTC_LINKER
 RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER)
 RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options
diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs
index eb2177202a2..d3ba477fa57 100644
--- a/src/test/run-pass/issue-10683.rs
+++ b/src/test/run-pass/issue-10683.rs
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-use std::ascii::AsciiExt;
-
 static NAME: &'static str = "hello world";
 
 fn main() {
diff --git a/src/test/run-pass/issue-27889.rs b/src/test/run-pass/issue-27889.rs
index 3f7d0400c88..29a5f6dd24b 100644
--- a/src/test/run-pass/issue-27889.rs
+++ b/src/test/run-pass/issue-27889.rs
@@ -10,7 +10,6 @@
 
 // Test that a field can have the same name in different variants
 // of an enum
-// FIXME #27889
 
 pub enum Foo {
     X { foo: u32 },
diff --git a/src/test/run-pass/issue-28561.rs b/src/test/run-pass/issue-28561.rs
index 8c73830f4d7..e21e487fedd 100644
--- a/src/test/run-pass/issue-28561.rs
+++ b/src/test/run-pass/issue-28561.rs
@@ -45,7 +45,7 @@ struct Array<T> {
     f32: [T; 32],
 }
 
-// FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone`
+// FIXME(#44580): merge with `Array` once `[T; N]: Clone` where `T: Clone`
 #[derive(Clone, Copy)]
 struct CopyArray<T: Copy> {
     f00: [T; 00],
diff --git a/src/test/rustdoc/check-styled-link.rs b/src/test/rustdoc/check-styled-link.rs
new file mode 100644
index 00000000000..1633711e83d
--- /dev/null
+++ b/src/test/rustdoc/check-styled-link.rs
@@ -0,0 +1,18 @@
+// 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.
+
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+// @has foo/struct.Bar.html '//a[@href="../foo/struct.Foo.html"]' 'Foo'
+
+/// Code-styled reference to [`Foo`].
+pub struct Bar;
diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs
index 8499e5c741e..ea8a13b034b 100644
--- a/src/test/rustdoc/doc-cfg.rs
+++ b/src/test/rustdoc/doc-cfg.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(doc_cfg)]
+#![feature(target_feature, cfg_target_feature)]
 
 // @has doc_cfg/struct.Portable.html
 // @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
@@ -45,3 +46,26 @@ pub mod unix_only {
         fn unix_and_arm_only_function() {}
     }
 }
+
+// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
+// item as well
+
+// the portability header is different on the module view versus the full view
+// @has doc_cfg/index.html
+// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+
+// @has doc_cfg/fn.uses_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+//        'This is supported with target feature avx only.'
+#[target_feature(enable = "avx")]
+pub unsafe fn uses_target_feature() {
+    content::should::be::irrelevant();
+}
+
+// @has doc_cfg/fn.uses_cfg_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+//        'This is supported with target feature avx only.'
+#[doc(cfg(target_feature = "avx"))]
+pub fn uses_cfg_target_feature() {
+    uses_target_feature();
+}
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
new file mode 100644
index 00000000000..010cb77edc3
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait.rs
@@ -0,0 +1,22 @@
+// 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.
+
+#![feature(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+trait Foo<S, T, U> {
+    fn s(S) -> S;
+    fn t(T) -> T;
+    fn u(U) -> U;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr
new file mode 100644
index 00000000000..6da1e2fd8ed
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait.stderr
@@ -0,0 +1,8 @@
+error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-dependent-def-issue-49241.rs b/src/test/ui/type-dependent-def-issue-49241.rs
new file mode 100644
index 00000000000..64264999fd2
--- /dev/null
+++ b/src/test/ui/type-dependent-def-issue-49241.rs
@@ -0,0 +1,15 @@
+// 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 main() {
+    let v = vec![0];
+    const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
+    let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
+}
diff --git a/src/test/ui/type-dependent-def-issue-49241.stderr b/src/test/ui/type-dependent-def-issue-49241.stderr
new file mode 100644
index 00000000000..f00edccae5d
--- /dev/null
+++ b/src/test/ui/type-dependent-def-issue-49241.stderr
@@ -0,0 +1,18 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/type-dependent-def-issue-49241.rs:13:22
+   |
+LL |     const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
+   |                      ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0080]: constant evaluation error
+  --> $DIR/type-dependent-def-issue-49241.rs:14:18
+   |
+LL |     let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
+   |                  ^ encountered constants with type errors, stopping evaluation
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0434.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 953a13a3f58..43220af4893 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1325,6 +1325,8 @@ impl<'test> TestCx<'test> {
 
         rustdoc
             .arg("-L")
+            .arg(self.config.run_lib_path.to_str().unwrap())
+            .arg("-L")
             .arg(aux_dir)
             .arg("-o")
             .arg(out_dir)
@@ -2358,11 +2360,6 @@ impl<'test> TestCx<'test> {
     }
 
     fn run_rmake_test(&self) {
-        // FIXME(#11094): we should fix these tests
-        if self.config.host != self.config.target {
-            return;
-        }
-
         let cwd = env::current_dir().unwrap();
         let src_root = self.config
             .src_base
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 0e3fa25b13c..c612f0117aa 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -14,21 +14,25 @@ use common::Config;
 /// Conversion table from triple OS name to Rust SYSNAME
 const OS_TABLE: &'static [(&'static str, &'static str)] = &[
     ("android", "android"),
+    ("androideabi", "android"),
     ("bitrig", "bitrig"),
     ("cloudabi", "cloudabi"),
     ("darwin", "macos"),
     ("dragonfly", "dragonfly"),
+    ("emscripten", "emscripten"),
     ("freebsd", "freebsd"),
+    ("fuchsia", "fuchsia"),
     ("haiku", "haiku"),
     ("ios", "ios"),
+    ("l4re", "l4re"),
     ("linux", "linux"),
     ("mingw32", "windows"),
     ("netbsd", "netbsd"),
     ("openbsd", "openbsd"),
+    ("redox", "redox"),
+    ("solaris", "solaris"),
     ("win32", "windows"),
     ("windows", "windows"),
-    ("solaris", "solaris"),
-    ("emscripten", "emscripten"),
 ];
 
 const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
@@ -36,20 +40,33 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
     ("amd64", "x86_64"),
     ("arm", "arm"),
     ("arm64", "aarch64"),
+    ("armv4t", "arm"),
+    ("armv5te", "arm"),
+    ("armv7", "arm"),
+    ("armv7s", "arm"),
+    ("asmjs", "asmjs"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),
     ("i686", "x86"),
-    ("mips64", "mips64"),
     ("mips", "mips"),
+    ("mips64", "mips64"),
+    ("mips64el", "mips64"),
+    ("mipsel", "mips"),
     ("msp430", "msp430"),
     ("powerpc", "powerpc"),
+    ("powerpc64", "powerpc64"),
+    ("powerpc64le", "powerpc64"),
     ("s390x", "s390x"),
     ("sparc", "sparc"),
+    ("sparc64", "sparc64"),
+    ("sparcv9", "sparc64"),
+    ("thumbv6m", "thumb"),
+    ("thumbv7em", "thumb"),
+    ("thumbv7m", "thumb"),
+    ("wasm32", "wasm32"),
     ("x86_64", "x86_64"),
     ("xcore", "xcore"),
-    ("asmjs", "asmjs"),
-    ("wasm32", "wasm32"),
 ];
 
 pub fn matches_os(triple: &str, name: &str) -> bool {
@@ -58,16 +75,18 @@ pub fn matches_os(triple: &str, name: &str) -> bool {
     if triple == "wasm32-unknown-unknown" {
         return name == "emscripten" || name == "wasm32-bare"
     }
+    let triple: Vec<_> = triple.split('-').collect();
     for &(triple_os, os) in OS_TABLE {
-        if triple.contains(triple_os) {
+        if triple.contains(&triple_os) {
             return os == name;
         }
     }
     panic!("Cannot determine OS from triple");
 }
 pub fn get_arch(triple: &str) -> &'static str {
+    let triple: Vec<_> = triple.split('-').collect();
     for &(triple_arch, arch) in ARCH_TABLE {
-        if triple.contains(triple_arch) {
+        if triple.contains(&triple_arch) {
             return arch;
         }
     }