about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Koch <nioko1337@gmail.com>2018-05-15 15:26:11 +0200
committerNicolas Koch <nioko1337@gmail.com>2018-05-15 15:26:11 +0200
commitb4b71d5d5fd8bedecbacf08ffb45c8456700151b (patch)
tree2ada477250001a23bc2d5329ca572e15b7bf23d7 /src
parent834ef9f08ae3429a05dead80237bb4bd04769895 (diff)
parenteca0da59850d4a9eef17c0e6c3795397102d88a3 (diff)
downloadrust-b4b71d5d5fd8bedecbacf08ffb45c8456700151b.tar.gz
rust-b4b71d5d5fd8bedecbacf08ffb45c8456700151b.zip
Merge branch 'master' of https://github.com/nicokoch/rust
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock7
-rw-r--r--src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md14
-rwxr-xr-xsrc/etc/generate-deriving-span-tests.py2
m---------src/libcompiler_builtins0
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc/ty/layout.rs5
-rw-r--r--src/librustc_metadata/lib.rs3
-rw-r--r--src/librustc_save_analysis/lib.rs2
-rw-r--r--src/librustc_trans/Cargo.toml1
-rw-r--r--src/librustc_trans/abi.rs5
-rw-r--r--src/librustc_trans/base.rs19
-rw-r--r--src/librustc_trans/builder.rs66
-rw-r--r--src/librustc_trans/intrinsic.rs34
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/mir/block.rs4
-rw-r--r--src/librustc_trans/mir/operand.rs25
-rw-r--r--src/librustc_typeck/check/_match.rs2
-rw-r--r--src/librustc_typeck/check/coercion.rs24
-rw-r--r--src/librustc_typeck/check/mod.rs36
-rw-r--r--src/librustdoc/html/render.rs38
-rw-r--r--src/librustdoc/html/static/main.js156
-rw-r--r--src/librustdoc/html/static/themes/dark.css9
-rw-r--r--src/librustdoc/html/static/themes/light.css7
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs14
-rw-r--r--src/libsyntax/feature_gate.rs8
-rw-r--r--src/libsyntax_ext/deriving/cmp/partial_ord.rs167
m---------src/stdsimd0
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs32
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs27
-rw-r--r--src/test/compile-fail/coerce-to-bang.rs5
-rw-r--r--src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs4
-rw-r--r--src/test/compile-fail/derives-span-PartialOrd-enum.rs4
-rw-r--r--src/test/compile-fail/derives-span-PartialOrd-struct.rs4
-rw-r--r--src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs4
-rw-r--r--src/test/compile-fail/range_traits-1.rs14
-rw-r--r--src/test/run-pass/issue-50731.rs (renamed from src/test/ui/feature-gate-macro-lifetime-matcher.rs)12
-rw-r--r--src/test/run-pass/macro-lifetime-used-with-bound.rs2
-rw-r--r--src/test/run-pass/macro-lifetime-used-with-labels.rs1
-rw-r--r--src/test/run-pass/macro-lifetime-used-with-static.rs2
-rw-r--r--src/test/run-pass/macro-lifetime.rs2
-rw-r--r--src/test/rustdoc-js/deduplication.js21
-rw-r--r--src/test/ui/feature-gate-macro-lifetime-matcher.stderr11
-rw-r--r--src/test/ui/macros/nonterminal-matching.rs2
m---------src/tools/clippy35
-rw-r--r--src/tools/rustdoc-js/tester.js5
45 files changed, 456 insertions, 382 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 4cb82f94251..2f52c889558 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -288,12 +288,12 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.0.198"
+version = "0.0.200"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
- "clippy_lints 0.0.198",
+ "clippy_lints 0.0.200",
  "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -331,7 +331,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.0.198"
+version = "0.0.200"
 dependencies = [
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2178,6 +2178,7 @@ dependencies = [
 name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md b/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md
deleted file mode 100644
index 5b585d7f041..00000000000
--- a/src/doc/unstable-book/src/language-features/macro-lifetime-matcher.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# `macro_lifetime_matcher`
-
-The tracking issue for this feature is: [#46895]
-
-With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry:
-
-* `lifetime`: a lifetime. Examples: 'static, 'a.
-
-A `lifetime` variable may be followed by anything.
-
-[#46895]: https://github.com/rust-lang/rust/issues/46895
-[frags]: ../book/first-edition/macros.html#syntactic-requirements
-
-------------------------
diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py
index edb9389c00c..2e9169ce5b9 100755
--- a/src/etc/generate-deriving-span-tests.py
+++ b/src/etc/generate-deriving-span-tests.py
@@ -122,7 +122,7 @@ traits = {
 
 for (trait, supers, errs) in [('Clone', [], 1),
                               ('PartialEq', [], 2),
-                              ('PartialOrd', ['PartialEq'], 5),
+                              ('PartialOrd', ['PartialEq'], 1),
                               ('Eq', ['PartialEq'], 1),
                               ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1),
                               ('Debug', [], 1),
diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins
-Subproject 2a2f6d96c8dc578d2474742f14c9bab0b36b040
+Subproject 4cfd7101eb549169cdaeda5313f7c39415b9d73
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 879d38c4894..2a288ae522a 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -50,7 +50,7 @@
 #![feature(from_ref)]
 #![feature(fs_read_write)]
 #![cfg_attr(windows, feature(libc))]
-#![feature(macro_lifetime_matcher)]
+#![cfg_attr(stage0, feature(macro_lifetime_matcher))]
 #![feature(macro_vis_matcher)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index b22c025e86c..bbfc6d883e9 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -888,6 +888,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     if x < min { min = x; }
                     if x > max { max = x; }
                 }
+                // We might have no inhabited variants, so pretend there's at least one.
+                if (min, max) == (i128::max_value(), i128::min_value()) {
+                    min = 0;
+                    max = 0;
+                }
                 assert!(min <= max, "discriminant range is {}...{}", min, max);
                 let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
 
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index a99e0a32e66..7ecf2eba43d 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -15,9 +15,8 @@
 #![feature(box_patterns)]
 #![feature(fs_read_write)]
 #![feature(libc)]
-#![feature(macro_lifetime_matcher)]
+#![cfg_attr(stage0, feature(macro_lifetime_matcher))]
 #![feature(proc_macro_internals)]
-#![feature(macro_lifetime_matcher)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index cf12302d989..e57a793ff42 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -12,7 +12,7 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(custom_attribute)]
-#![feature(macro_lifetime_matcher)]
+#![cfg_attr(stage0, feature(macro_lifetime_matcher))]
 #![allow(unused_attributes)]
 
 #[macro_use]
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index a4dd02e97b2..64d3a4f4d53 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -10,6 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
+bitflags = "1.0.1"
 cc = "1.0.1"
 flate2 = "1.0"
 jobserver = "0.1.5"
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 1838dae049a..25c598c532c 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -10,7 +10,7 @@
 
 use llvm::{self, ValueRef, AttributePlace};
 use base;
-use builder::Builder;
+use builder::{Builder, MemFlags};
 use common::{ty_fn_sig, C_usize};
 use context::CodegenCx;
 use mir::place::PlaceRef;
@@ -220,7 +220,8 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
                                   bx.pointercast(dst.llval, Type::i8p(cx)),
                                   bx.pointercast(llscratch, Type::i8p(cx)),
                                   C_usize(cx, self.layout.size.bytes()),
-                                  self.layout.align.min(scratch_align));
+                                  self.layout.align.min(scratch_align),
+                                  MemFlags::empty());
 
                 bx.lifetime_end(llscratch, scratch_size);
             }
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 0dd1adbff86..feca36fa6c2 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -53,7 +53,7 @@ use rustc_incremental;
 use allocator;
 use mir::place::PlaceRef;
 use attributes;
-use builder::Builder;
+use builder::{Builder, MemFlags};
 use callee;
 use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
 use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
@@ -320,7 +320,7 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
                 if src_f.layout.ty == dst_f.layout.ty {
                     memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout,
-                        src_f.align.min(dst_f.align));
+                              src_f.align.min(dst_f.align), MemFlags::empty());
                 } else {
                     coerce_unsized_into(bx, src_f, dst_f);
                 }
@@ -408,7 +408,15 @@ pub fn call_memcpy(bx: &Builder,
                    dst: ValueRef,
                    src: ValueRef,
                    n_bytes: ValueRef,
-                   align: Align) {
+                   align: Align,
+                   flags: MemFlags) {
+    if flags.contains(MemFlags::NONTEMPORAL) {
+        // HACK(nox): This is inefficient but there is no nontemporal memcpy.
+        let val = bx.load(src, align);
+        let ptr = bx.pointercast(dst, val_ty(val).ptr_to());
+        bx.store_with_flags(val, ptr, align, flags);
+        return;
+    }
     let cx = bx.cx;
     let ptr_width = &cx.sess().target.target.target_pointer_width;
     let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
@@ -417,7 +425,7 @@ pub fn call_memcpy(bx: &Builder,
     let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
     let size = bx.intcast(n_bytes, cx.isize_ty, false);
     let align = C_i32(cx, align.abi() as i32);
-    let volatile = C_bool(cx, false);
+    let volatile = C_bool(cx, flags.contains(MemFlags::VOLATILE));
     bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
 }
 
@@ -427,13 +435,14 @@ pub fn memcpy_ty<'a, 'tcx>(
     src: ValueRef,
     layout: TyLayout<'tcx>,
     align: Align,
+    flags: MemFlags,
 ) {
     let size = layout.size.bytes();
     if size == 0 {
         return;
     }
 
-    call_memcpy(bx, dst, src, C_usize(bx.cx, size), align);
+    call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags);
 }
 
 pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index db803ca8209..4153c61e526 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -50,6 +50,13 @@ fn noname() -> *const c_char {
     &CNULL
 }
 
+bitflags! {
+    pub struct MemFlags: u8 {
+        const VOLATILE = 1 << 0;
+        const NONTEMPORAL = 1 << 1;
+    }
+}
+
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
         let bx = Builder::with_cx(cx);
@@ -579,29 +586,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef {
-        debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
+        self.store_with_flags(val, ptr, align, MemFlags::empty())
+    }
+
+    pub fn store_with_flags(
+        &self,
+        val: ValueRef,
+        ptr: ValueRef,
+        align: Align,
+        flags: MemFlags,
+    ) -> ValueRef {
+        debug!("Store {:?} -> {:?} ({:?})", Value(val), Value(ptr), flags);
         assert!(!self.llbuilder.is_null());
         self.count_insn("store");
         let ptr = self.check_store(val, ptr);
         unsafe {
             let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
             llvm::LLVMSetAlignment(store, align.abi() as c_uint);
+            if flags.contains(MemFlags::VOLATILE) {
+                llvm::LLVMSetVolatile(store, llvm::True);
+            }
+            if flags.contains(MemFlags::NONTEMPORAL) {
+                // According to LLVM [1] building a nontemporal store must
+                // *always* point to a metadata value of the integer 1.
+                //
+                // [1]: http://llvm.org/docs/LangRef.html#store-instruction
+                let one = C_i32(self.cx, 1);
+                let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
+                llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
+            }
             store
         }
     }
 
-    pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
-        debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
-        assert!(!self.llbuilder.is_null());
-        self.count_insn("store.volatile");
-        let ptr = self.check_store(val, ptr);
-        unsafe {
-            let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
-            llvm::LLVMSetVolatile(insn, llvm::True);
-            insn
-        }
-    }
-
     pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef,
                         order: AtomicOrdering, align: Align) {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
@@ -615,29 +632,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn nontemporal_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
-        debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
-        assert!(!self.llbuilder.is_null());
-        self.count_insn("store.nontemporal");
-        let ptr = self.check_store(val, ptr);
-        unsafe {
-            let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
-
-            // According to LLVM [1] building a nontemporal store must *always*
-            // point to a metadata value of the integer 1. Who knew?
-            //
-            // [1]: http://llvm.org/docs/LangRef.html#store-instruction
-            let one = C_i32(self.cx, 1);
-            let node = llvm::LLVMMDNodeInContext(self.cx.llcx,
-                                                 &one,
-                                                 1);
-            llvm::LLVMSetMetadata(insn,
-                                  llvm::MD_nontemporal as c_uint,
-                                  node);
-            insn
-        }
-    }
-
     pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
         self.count_insn("gep");
         unsafe {
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 49a207a2d8a..86aa48b6a9e 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -247,26 +247,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             to_immediate(bx, load, cx.layout_of(tp_ty))
         },
         "volatile_store" => {
-            let tp_ty = substs.type_at(0);
             let dst = args[0].deref(bx.cx);
-            if let OperandValue::Pair(a, b) = args[1].val {
-                bx.volatile_store(a, dst.project_field(bx, 0).llval);
-                bx.volatile_store(b, dst.project_field(bx, 1).llval);
-            } else {
-                let val = if let OperandValue::Ref(ptr, align) = args[1].val {
-                    bx.load(ptr, align)
-                } else {
-                    if dst.layout.is_zst() {
-                        return;
-                    }
-                    from_immediate(bx, args[1].immediate())
-                };
-                let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
-                let store = bx.volatile_store(val, ptr);
-                unsafe {
-                    llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
-                }
-            }
+            args[1].val.volatile_store(bx, dst);
             return;
         },
         "prefetch_read_data" | "prefetch_write_data" |
@@ -551,19 +533,9 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
         }
 
         "nontemporal_store" => {
-            let tp_ty = substs.type_at(0);
             let dst = args[0].deref(bx.cx);
-            let val = if let OperandValue::Ref(ptr, align) = args[1].val {
-                bx.load(ptr, align)
-            } else {
-                from_immediate(bx, args[1].immediate())
-            };
-            let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
-            let store = bx.nontemporal_store(val, ptr);
-            unsafe {
-                llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
-            }
-            return
+            args[1].val.nontemporal_store(bx, dst);
+            return;
         }
 
         _ => {
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 30780b8c965..6db95657ce0 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -34,6 +34,7 @@
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
+#[macro_use] extern crate bitflags;
 extern crate flate2;
 extern crate libc;
 #[macro_use] extern crate rustc;
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index b666c2b2115..e4989da36c0 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -17,7 +17,7 @@ use rustc::mir::interpret::EvalErrorKind;
 use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode};
 use base;
 use callee;
-use builder::Builder;
+use builder::{Builder, MemFlags};
 use common::{self, C_bool, C_str_slice, C_struct, C_u32, C_uint_big, C_undef};
 use consts;
 use meth;
@@ -626,7 +626,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     // have scary latent bugs around.
 
                     let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
-                    base::memcpy_ty(bx, scratch.llval, llval, op.layout, align);
+                    base::memcpy_ty(bx, scratch.llval, llval, op.layout, align, MemFlags::empty());
                     (scratch.llval, scratch.align, true)
                 } else {
                     (llval, align, true)
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index d2bf8394296..be14da1a195 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::indexed_vec::Idx;
 
 use base;
 use common::{self, CodegenCx, C_null, C_undef, C_usize};
-use builder::Builder;
+use builder::{Builder, MemFlags};
 use value::Value;
 use type_of::LayoutLlvmExt;
 use type_::Type;
@@ -272,6 +272,18 @@ impl<'a, 'tcx> OperandRef<'tcx> {
 
 impl<'a, 'tcx> OperandValue {
     pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+        self.store_with_flags(bx, dest, MemFlags::empty());
+    }
+
+    pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+        self.store_with_flags(bx, dest, MemFlags::VOLATILE);
+    }
+
+    pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+        self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL);
+    }
+
+    fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: MemFlags) {
         debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
         // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
         // value is through `undef`, and store itself is useless.
@@ -279,11 +291,13 @@ impl<'a, 'tcx> OperandValue {
             return;
         }
         match self {
-            OperandValue::Ref(r, source_align) =>
+            OperandValue::Ref(r, source_align) => {
                 base::memcpy_ty(bx, dest.llval, r, dest.layout,
-                                source_align.min(dest.align)),
+                                source_align.min(dest.align), flags)
+            }
             OperandValue::Immediate(s) => {
-                bx.store(base::from_immediate(bx, s), dest.llval, dest.align);
+                let val = base::from_immediate(bx, s);
+                bx.store_with_flags(val, dest.llval, dest.align, flags);
             }
             OperandValue::Pair(a, b) => {
                 for (i, &x) in [a, b].iter().enumerate() {
@@ -292,7 +306,8 @@ impl<'a, 'tcx> OperandValue {
                     if common::val_ty(x) == Type::i1(bx.cx) {
                         llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
                     }
-                    bx.store(base::from_immediate(bx, x), llptr, dest.align);
+                    let val = base::from_immediate(bx, x);
+                    bx.store_with_flags(val, llptr, dest.align, flags);
                 }
             }
         }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 2547952d104..35cc70b0838 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -688,7 +688,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                     arm_span: arm.body.span,
                     source: match_src
                 });
-                coercion.coerce(self, &cause, &arm.body, arm_ty, self.diverges.get());
+                coercion.coerce(self, &cause, &arm.body, arm_ty);
             }
         }
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index c1ef916e27d..324af7b6270 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -60,7 +60,7 @@
 //! sort of a minor point so I've opted to leave it for later---after all
 //! we may want to adjust precisely when coercions occur.
 
-use check::{Diverges, FnCtxt, Needs};
+use check::{FnCtxt, Needs};
 
 use rustc::hir;
 use rustc::hir::def_id::DefId;
@@ -800,8 +800,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 exprs: &[E],
                                 prev_ty: Ty<'tcx>,
                                 new: &hir::Expr,
-                                new_ty: Ty<'tcx>,
-                                new_diverges: Diverges)
+                                new_ty: Ty<'tcx>)
                                 -> RelateResult<'tcx, Ty<'tcx>>
         where E: AsCoercionSite
     {
@@ -809,13 +808,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let new_ty = self.resolve_type_vars_with_obligations(new_ty);
         debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty);
 
-        // Special-ish case: we can coerce any type `T` into the `!`
-        // type, but only if the source expression diverges.
-        if prev_ty.is_never() && new_diverges.always() {
-            debug!("permit coercion to `!` because expr diverges");
-            return Ok(prev_ty);
-        }
-
         // Special-case that coercion alone cannot handle:
         // Two function item types of differing IDs or Substs.
         if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
@@ -1054,14 +1046,12 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                       fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                       cause: &ObligationCause<'tcx>,
                       expression: &'gcx hir::Expr,
-                      expression_ty: Ty<'tcx>,
-                      expression_diverges: Diverges)
+                      expression_ty: Ty<'tcx>)
     {
         self.coerce_inner(fcx,
                           cause,
                           Some(expression),
                           expression_ty,
-                          expression_diverges,
                           None, false)
     }
 
@@ -1087,7 +1077,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                           cause,
                           None,
                           fcx.tcx.mk_nil(),
-                          Diverges::Maybe,
                           Some(augment_error),
                           label_unit_as_expected)
     }
@@ -1100,7 +1089,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                         cause: &ObligationCause<'tcx>,
                         expression: Option<&'gcx hir::Expr>,
                         mut expression_ty: Ty<'tcx>,
-                        expression_diverges: Diverges,
                         augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>,
                         label_expression_as_expected: bool)
     {
@@ -1134,15 +1122,13 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                                                   exprs,
                                                   self.merged_ty(),
                                                   expression,
-                                                  expression_ty,
-                                                  expression_diverges),
+                                                  expression_ty),
                     Expressions::UpFront(ref coercion_sites) =>
                         fcx.try_find_coercion_lub(cause,
                                                   &coercion_sites[0..self.pushed],
                                                   self.merged_ty(),
                                                   expression,
-                                                  expression_ty,
-                                                  expression_diverges),
+                                                  expression_ty),
                 }
             }
         } else {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b9c035e1ca1..b4a7de7b844 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -542,7 +542,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// you get indicates whether any subexpression that was
     /// evaluating up to and including `X` diverged.
     ///
-    /// We use this flag for two purposes:
+    /// We currently use this flag only for diagnostic purposes:
     ///
     /// - To warn about unreachable code: if, after processing a
     ///   sub-expression but before we have applied the effects of the
@@ -556,16 +556,8 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     ///   foo();}` or `{return; 22}`, where we would warn on the
     ///   `foo()` or `22`.
     ///
-    /// - To permit assignment into a local variable or other place
-    ///   (including the "return slot") of type `!`.  This is allowed
-    ///   if **either** the type of value being assigned is `!`, which
-    ///   means the current code is dead, **or** the expression's
-    ///   diverging flag is true, which means that a diverging value was
-    ///   wrapped (e.g., `let x: ! = foo(return)`).
-    ///
-    /// To repeat the last point: an expression represents dead-code
-    /// if, after checking it, **either** its type is `!` OR the
-    /// diverges flag is set to something other than `Maybe`.
+    /// An expression represents dead-code if, after checking it,
+    /// the diverges flag is set to something other than `Maybe`.
     diverges: Cell<Diverges>,
 
     /// Whether any child nodes have any type errors.
@@ -3002,8 +2994,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             &self.cause(return_expr.span,
                                         ObligationCauseCode::ReturnType(return_expr.id)),
                             return_expr,
-                            return_expr_ty,
-                            self.diverges.get());
+                            return_expr_ty);
     }
 
 
@@ -3034,13 +3025,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let mut coerce: DynamicCoerceMany = CoerceMany::new(coerce_to_ty);
 
         let if_cause = self.cause(sp, ObligationCauseCode::IfExpression);
-        coerce.coerce(self, &if_cause, then_expr, then_ty, then_diverges);
+        coerce.coerce(self, &if_cause, then_expr, then_ty);
 
         if let Some(else_expr) = opt_else_expr {
             let else_ty = self.check_expr_with_expectation(else_expr, expected);
             let else_diverges = self.diverges.get();
 
-            coerce.coerce(self, &if_cause, else_expr, else_ty, else_diverges);
+            coerce.coerce(self, &if_cause, else_expr, else_ty);
 
             // We won't diverge unless both branches do (or the condition does).
             self.diverges.set(cond_diverges | then_diverges & else_diverges);
@@ -3081,12 +3072,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     if let Some(index) = fields.iter().position(|f| f.name.to_ident() == ident) {
                         let field = &fields[index];
                         let field_ty = self.field_ty(expr.span, field, substs);
+                        // Save the index of all fields regardless of their visibility in case
+                        // of error recovery.
+                        self.write_field_index(expr.id, index);
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
                             let adjustments = autoderef.adjust_steps(needs);
                             self.apply_adjustments(base, adjustments);
                             autoderef.finalize();
 
-                            self.write_field_index(expr.id, index);
                             self.tcx.check_stability(field.did, Some(expr.id), expr.span);
                             return field_ty;
                         }
@@ -3731,7 +3724,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
           }
           hir::ExprBreak(destination, ref expr_opt) => {
               if let Some(target_id) = destination.target_id.opt_id() {
-                  let (e_ty, e_diverges, cause);
+                  let (e_ty, cause);
                   if let Some(ref e) = *expr_opt {
                       // If this is a break with a value, we need to type-check
                       // the expression. Get an expected type from the loop context.
@@ -3750,13 +3743,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                       // Recurse without `enclosing_breakables` borrowed.
                       e_ty = self.check_expr_with_hint(e, coerce_to);
-                      e_diverges = self.diverges.get();
                       cause = self.misc(e.span);
                   } else {
                       // Otherwise, this is a break *without* a value. That's
                       // always legal, and is equivalent to `break ()`.
                       e_ty = tcx.mk_nil();
-                      e_diverges = Diverges::Maybe;
                       cause = self.misc(expr.span);
                   }
 
@@ -3767,7 +3758,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                   let ctxt = enclosing_breakables.find_breakable(target_id);
                   if let Some(ref mut coerce) = ctxt.coerce {
                       if let Some(ref e) = *expr_opt {
-                          coerce.coerce(self, &cause, e, e_ty, e_diverges);
+                          coerce.coerce(self, &cause, e, e_ty);
                       } else {
                           assert!(e_ty.is_nil());
                           coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
@@ -3973,7 +3964,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                   for e in args {
                       let e_ty = self.check_expr_with_hint(e, coerce_to);
                       let cause = self.misc(e.span);
-                      coerce.coerce(self, &cause, e, e_ty, self.diverges.get());
+                      coerce.coerce(self, &cause, e, e_ty);
                   }
                   coerce.complete(self)
               } else {
@@ -4384,8 +4375,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 coerce.coerce(self,
                               &cause,
                               tail_expr,
-                              tail_expr_ty,
-                              self.diverges.get());
+                              tail_expr_ty);
             } else {
                 // Subtle: if there is no explicit tail expression,
                 // that is typically equivalent to a tail expression
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index fe9fc3ddd68..32cfb05bbe4 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -413,9 +413,9 @@ impl ToJson for Type {
         match self.name {
             Some(ref name) => {
                 let mut data = BTreeMap::new();
-                data.insert("name".to_owned(), name.to_json());
+                data.insert("n".to_owned(), name.to_json());
                 if let Some(ref generics) = self.generics {
-                    data.insert("generics".to_owned(), generics.to_json());
+                    data.insert("g".to_owned(), generics.to_json());
                 }
                 Json::Object(data)
             },
@@ -438,8 +438,12 @@ impl ToJson for IndexItemFunctionType {
             Json::Null
         } else {
             let mut data = BTreeMap::new();
-            data.insert("inputs".to_owned(), self.inputs.to_json());
-            data.insert("output".to_owned(), self.output.to_json());
+            if !self.inputs.is_empty() {
+                data.insert("i".to_owned(), self.inputs.to_json());
+            }
+            if let Some(ref output) = self.output {
+                data.insert("o".to_owned(), output.to_json());
+            }
             Json::Object(data)
         }
     }
@@ -789,7 +793,8 @@ fn write_shared(cx: &Context,
           format!(
 r#"var themes = document.getElementById("theme-choices");
 var themePicker = document.getElementById("theme-picker");
-themePicker.onclick = function() {{
+
+function switchThemeButtonState() {{
     if (themes.style.display === "block") {{
         themes.style.display = "none";
         themePicker.style.borderBottomRightRadius = "3px";
@@ -800,12 +805,29 @@ themePicker.onclick = function() {{
         themePicker.style.borderBottomLeftRadius = "0";
     }}
 }};
+
+function handleThemeButtonsBlur(e) {{
+    var active = document.activeElement;
+    var related = e.relatedTarget;
+
+    if (active.id !== "themePicker" &&
+        (!active.parentNode || active.parentNode.id !== "theme-choices") &&
+        (!related ||
+         (related.id !== "themePicker" &&
+          (!related.parentNode || related.parentNode.id !== "theme-choices")))) {{
+        switchThemeButtonState();
+    }}
+}}
+
+themePicker.onclick = switchThemeButtonState;
+themePicker.onblur = handleThemeButtonsBlur;
 [{}].forEach(function(item) {{
     var but = document.createElement('button');
     but.innerHTML = item;
     but.onclick = function(el) {{
         switchTheme(currentTheme, mainTheme, item);
     }};
+    but.onblur = handleThemeButtonsBlur;
     themes.appendChild(but);
 }});"#,
                  themes.iter()
@@ -879,8 +901,8 @@ themePicker.onclick = function() {{
     }
 
     fn show_item(item: &IndexItem, krate: &str) -> String {
-        format!("{{'crate':'{}','ty':{},'name':'{}','path':'{}'{}}}",
-                krate, item.ty as usize, item.name, item.path,
+        format!("{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}",
+                krate, item.ty as usize, item.name, item.desc.replace("'", "\\'"), item.path,
                 if let Some(p) = item.parent_idx {
                     format!(",'parent':{}", p)
                 } else {
@@ -1442,7 +1464,7 @@ impl<'a> Cache {
                                 ty: item.type_(),
                                 name: item_name.to_string(),
                                 path: path.clone(),
-                                desc: String::new(),
+                                desc: plain_summary_line(item.doc_value()),
                                 parent: None,
                                 parent_idx: None,
                                 search_type: get_index_search_type(&item),
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 8569abeb09c..9224bd1c508 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -57,6 +57,12 @@
             return this.indexOf(searchString, position) === position;
         };
     }
+    if (!String.prototype.endsWith) {
+        String.prototype.endsWith = function(suffix, length) {
+            var l = length || this.length;
+            return this.indexOf(suffix, l - suffix.length) !== -1;
+        };
+    }
 
     function getPageId() {
         var id = document.location.href.split('#')[1];
@@ -454,12 +460,16 @@
                         var obj = searchIndex[results[i].id];
                         obj.lev = results[i].lev;
                         if (isType !== true || obj.type) {
+                            var res = buildHrefAndPath(obj);
+                            obj.displayPath = pathSplitter(res[0]);
+                            obj.fullPath = obj.displayPath + obj.name;
+                            obj.href = res[1];
                             out.push(obj);
+                            if (out.length >= MAX_RESULTS) {
+                                break;
+                            }
                         }
                     }
-                    if (out.length >= MAX_RESULTS) {
-                        break;
-                    }
                 }
                 return out;
             }
@@ -587,8 +597,8 @@
                 // match as well.
                 var lev_distance = MAX_LEV_DISTANCE + 1;
                 if (val.generics.length > 0) {
-                    if (obj.generics && obj.generics.length >= val.generics.length) {
-                        var elems = obj.generics.slice(0);
+                    if (obj.g && obj.g.length >= val.generics.length) {
+                        var elems = obj.g.slice(0);
                         var total = 0;
                         var done = 0;
                         // We need to find the type that matches the most to remove it in order
@@ -620,11 +630,11 @@
             // Check for type name and type generics (if any).
             function checkType(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
-                if (obj.name === val.name) {
+                if (obj.n === val.name) {
                     if (literalSearch === true) {
                         if (val.generics && val.generics.length !== 0) {
-                            if (obj.generics && obj.length >= val.generics.length) {
-                                var elems = obj.generics.slice(0);
+                            if (obj.g && obj.length >= val.generics.length) {
+                                var elems = obj.g.slice(0);
                                 var allFound = true;
                                 var x;
 
@@ -648,7 +658,7 @@
                     }
                     // If the type has generics but don't match, then it won't return at this point.
                     // Otherwise, `checkGenerics` will return 0 and it'll return.
-                    if (obj.generics && obj.generics.length !== 0) {
+                    if (obj.g && obj.g.length !== 0) {
                         var tmp_lev = checkGenerics(obj, val);
                         if (tmp_lev <= MAX_LEV_DISTANCE) {
                             return tmp_lev;
@@ -659,22 +669,22 @@
                 }
                 // Names didn't match so let's check if one of the generic types could.
                 if (literalSearch === true) {
-                     if (obj.generics && obj.generics.length > 0) {
-                        for (var x = 0; x < obj.generics.length; ++x) {
-                            if (obj.generics[x] === val.name) {
+                     if (obj.g && obj.g.length > 0) {
+                        for (var x = 0; x < obj.g.length; ++x) {
+                            if (obj.g[x] === val.name) {
                                 return true;
                             }
                         }
                     }
                     return false;
                 }
-                var lev_distance = Math.min(levenshtein(obj.name, val.name), lev_distance);
+                var lev_distance = Math.min(levenshtein(obj.n, val.name), lev_distance);
                 if (lev_distance <= MAX_LEV_DISTANCE) {
                     lev_distance = Math.min(checkGenerics(obj, val), lev_distance);
-                } else if (obj.generics && obj.generics.length > 0) {
+                } else if (obj.g && obj.g.length > 0) {
                     // We can check if the type we're looking for is inside the generics!
-                    for (var x = 0; x < obj.generics.length; ++x) {
-                        lev_distance = Math.min(levenshtein(obj.generics[x], val.name),
+                    for (var x = 0; x < obj.g.length; ++x) {
+                        lev_distance = Math.min(levenshtein(obj.g[x], val.name),
                                                 lev_distance);
                     }
                 }
@@ -686,9 +696,9 @@
             function findArg(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
-                if (obj && obj.type && obj.type.inputs.length > 0) {
-                    for (var i = 0; i < obj.type.inputs.length; i++) {
-                        var tmp = checkType(obj.type.inputs[i], val, literalSearch);
+                if (obj && obj.type && obj.type.i && obj.type.i.length > 0) {
+                    for (var i = 0; i < obj.type.i.length; i++) {
+                        var tmp = checkType(obj.type.i[i], val, literalSearch);
                         if (literalSearch === true && tmp === true) {
                             return true;
                         }
@@ -704,8 +714,8 @@
             function checkReturned(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
-                if (obj && obj.type && obj.type.output) {
-                    var tmp = checkType(obj.type.output, val, literalSearch);
+                if (obj && obj.type && obj.type.o) {
+                    var tmp = checkType(obj.type.o, val, literalSearch);
                     if (literalSearch === true && tmp === true) {
                         return true;
                     }
@@ -850,7 +860,7 @@
                     var fullId = generateId(ty);
 
                     // allow searching for void (no output) functions as well
-                    var typeOutput = type.output ? type.output.name : "";
+                    var typeOutput = type.o ? type.o.name : "";
                     var returned = checkReturned(ty, output, true);
                     if (output.name === "*" || returned === true) {
                         var in_args = false;
@@ -1017,6 +1027,13 @@
                     ALIASES[window.currentCrate][query.raw]) {
                 var aliases = ALIASES[window.currentCrate][query.raw];
                 for (var i = 0; i < aliases.length; ++i) {
+                    aliases[i].is_alias = true;
+                    aliases[i].alias = query.raw;
+                    aliases[i].path = aliases[i].p;
+                    var res = buildHrefAndPath(aliases[i]);
+                    aliases[i].displayPath = pathSplitter(res[0]);
+                    aliases[i].fullPath = aliases[i].displayPath + aliases[i].name;
+                    aliases[i].href = res[1];
                     ret['others'].unshift(aliases[i]);
                     if (ret['others'].length > MAX_RESULTS) {
                         ret['others'].pop();
@@ -1179,16 +1196,6 @@
             };
         }
 
-        function escape(content) {
-            var h1 = document.createElement('h1');
-            h1.textContent = content;
-            return h1.innerHTML;
-        }
-
-        function pathSplitter(path) {
-            return '<span>' + path.replace(/::/g, '::</span><span>');
-        }
-
         function buildHrefAndPath(item) {
             var displayPath;
             var href;
@@ -1227,6 +1234,20 @@
             return [displayPath, href];
         }
 
+        function escape(content) {
+            var h1 = document.createElement('h1');
+            h1.textContent = content;
+            return h1.innerHTML;
+        }
+
+        function pathSplitter(path) {
+            var tmp = '<span>' + path.replace(/::/g, '::</span><span>');
+            if (tmp.endsWith("<span>")) {
+                return tmp.slice(0, tmp.length - 6);
+            }
+            return tmp;
+        }
+
         function addTab(array, query, display) {
             var extraStyle = '';
             if (display === false) {
@@ -1234,31 +1255,33 @@
             }
 
             var output = '';
+            var duplicates = {};
+            var length = 0;
             if (array.length > 0) {
                 output = '<table class="search-results"' + extraStyle + '>';
-                var shown = [];
 
                 array.forEach(function(item) {
-                    var name, type, href, displayPath;
-
-                    var id_ty = item.ty + item.path + item.name;
-                    if (shown.indexOf(id_ty) !== -1) {
-                        return;
-                    }
+                    var name, type;
 
-                    shown.push(id_ty);
                     name = item.name;
                     type = itemTypes[item.ty];
 
-                    var res = buildHrefAndPath(item);
-                    var href = res[1];
-                    var displayPath = res[0];
+                    if (item.is_alias !== true) {
+                        if (duplicates[item.fullPath]) {
+                            return;
+                        }
+                        duplicates[item.fullPath] = true;
+                    }
+                    length += 1;
 
                     output += '<tr class="' + type + ' result"><td>' +
-                              '<a href="' + href + '">' +
-                              pathSplitter(displayPath) + '<span class="' + type + '">' +
+                              '<a href="' + item.href + '">' +
+                              (item.is_alias === true ?
+                               ('<span class="alias"><b>' + item.alias + ' </b></span><span ' +
+                                  'class="grey"><i>&nbsp;- see&nbsp;</i></span>') : '') +
+                              item.displayPath + '<span class="' + type + '">' +
                               name + '</span></a></td><td>' +
-                              '<a href="' + href + '">' +
+                              '<a href="' + item.href + '">' +
                               '<span class="desc">' + escape(item.desc) +
                               '&nbsp;</span></a></td></tr>';
                 });
@@ -1269,7 +1292,7 @@
                     encodeURIComponent('rust ' + query.query) +
                     '">DuckDuckGo</a>?</div>';
             }
-            return output;
+            return [output, length];
         }
 
         function makeTabHeader(tabNb, text, nbElems) {
@@ -1284,28 +1307,28 @@
             if (results['others'].length === 1 &&
                 getCurrentValue('rustdoc-go-to-only-result') === "true") {
                 var elem = document.createElement('a');
-                var res = buildHrefAndPath(results['others'][0]);
-                elem.href = res[1];
+                elem.href = results['others'][0].href;
                 elem.style.display = 'none';
                 // For firefox, we need the element to be in the DOM so it can be clicked.
                 document.body.appendChild(elem);
                 elem.click();
             }
-            var output, query = getQuery(search_input.value);
+            var query = getQuery(search_input.value);
 
             currentResults = query.id;
-            output = '<h1>Results for ' + escape(query.query) +
+
+            var ret_others = addTab(results['others'], query);
+            var ret_in_args = addTab(results['in_args'], query, false);
+            var ret_returned = addTab(results['returned'], query, false);
+
+            var output = '<h1>Results for ' + escape(query.query) +
                 (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
                 '<div id="titles">' +
-                makeTabHeader(0, "In Names", results['others'].length) +
-                makeTabHeader(1, "In Parameters", results['in_args'].length) +
-                makeTabHeader(2, "In Return Types", results['returned'].length) +
-                '</div><div id="results">';
-
-            output += addTab(results['others'], query);
-            output += addTab(results['in_args'], query, false);
-            output += addTab(results['returned'], query, false);
-            output += '</div>';
+                makeTabHeader(0, "In Names", ret_others[1]) +
+                makeTabHeader(1, "In Parameters", ret_in_args[1]) +
+                makeTabHeader(2, "In Return Types", ret_returned[1]) +
+                '</div><div id="results">' +
+                ret_others[0] + ret_in_args[0] + ret_returned[0] + '</div>';
 
             addClass(document.getElementById('main'), 'hidden');
             var search = document.getElementById('search');
@@ -1347,12 +1370,13 @@
                 }
             }
             if (queries.length > 1) {
-                function getSmallest(arrays, positions) {
+                function getSmallest(arrays, positions, notDuplicates) {
                     var start = null;
 
                     for (var it = 0; it < positions.length; ++it) {
                         if (arrays[it].length > positions[it] &&
-                            (start === null || start > arrays[it][positions[it]].lev)) {
+                            (start === null || start > arrays[it][positions[it]].lev) &&
+                            !notDuplicates[arrays[it][positions[it]].fullPath]) {
                             start = arrays[it][positions[it]].lev;
                         }
                     }
@@ -1362,19 +1386,23 @@
                 function mergeArrays(arrays) {
                     var ret = [];
                     var positions = [];
+                    var notDuplicates = {};
 
                     for (var x = 0; x < arrays.length; ++x) {
                         positions.push(0);
                     }
                     while (ret.length < MAX_RESULTS) {
-                        var smallest = getSmallest(arrays, positions);
+                        var smallest = getSmallest(arrays, positions, notDuplicates);
+
                         if (smallest === null) {
                             break;
                         }
                         for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
                             if (arrays[x].length > positions[x] &&
-                                    arrays[x][positions[x]].lev === smallest) {
+                                    arrays[x][positions[x]].lev === smallest &&
+                                    !notDuplicates[arrays[x][positions[x]].fullPath]) {
                                 ret.push(arrays[x][positions[x]]);
+                                notDuplicates[arrays[x][positions[x]].fullPath] = true;
                                 positions[x] += 1;
                             }
                         }
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index da4be7db5aa..493a75e2521 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -382,7 +382,7 @@ kbd {
 }
 
 #theme-choices > button:hover, #theme-choices > button:focus {
-	background-color: #444;
+	background-color: #4e4e4e;
 }
 
 @media (max-width: 700px) {
@@ -397,3 +397,10 @@ kbd {
 #all-types:hover {
 	background-color: #606060;
 }
+
+.search-results td span.alias {
+	color: #fff;
+}
+.search-results td span.grey {
+	color: #ccc;
+}
\ No newline at end of file
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 12af01d2e24..22f4635fb02 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -390,4 +390,11 @@ kbd {
 }
 #all-types:hover {
 	background-color: #f9f9f9;
+}
+
+.search-results td span.alias {
+	color: #000;
+}
+.search-results td span.grey {
+	color: #999;
 }
\ No newline at end of file
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 1fc5aed7e7a..e96a0e838cf 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -904,20 +904,8 @@ fn is_legal_fragment_specifier(sess: &ParseSess,
                                frag_name: &str,
                                frag_span: Span) -> bool {
     match frag_name {
-        "item" | "block" | "stmt" | "expr" | "pat" |
+        "item" | "block" | "stmt" | "expr" | "pat" | "lifetime" |
         "path" | "ty" | "ident" | "meta" | "tt" | "" => true,
-        "lifetime" => {
-            if !features.macro_lifetime_matcher &&
-               !attr::contains_name(attrs, "allow_internal_unstable") {
-                let explain = feature_gate::EXPLAIN_LIFETIME_MATCHER;
-                emit_feature_err(sess,
-                                 "macro_lifetime_matcher",
-                                 frag_span,
-                                 GateIssue::Language,
-                                 explain);
-            }
-            true
-        },
         "literal" => {
             if !features.macro_literal_matcher &&
                !attr::contains_name(attrs, "allow_internal_unstable") {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 562705462e2..cb5125fe9ef 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -396,9 +396,6 @@ declare_features! (
     // Termination trait in tests (RFC 1937)
     (active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)),
 
-    // Allows use of the :lifetime macro fragment specifier
-    (active, macro_lifetime_matcher, "1.24.0", Some(46895), None),
-
     // `extern` in paths
     (active, extern_in_paths, "1.23.0", Some(44660), None),
 
@@ -598,6 +595,8 @@ declare_features! (
     (accepted, dyn_trait, "1.27.0", Some(44662), None),
     // allow `#[must_use]` on functions; and, must-use operators (RFC 1940)
     (accepted, fn_must_use, "1.27.0", Some(43302), None),
+    // Allows use of the :lifetime macro fragment specifier
+    (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -1331,9 +1330,6 @@ pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
 pub const EXPLAIN_VIS_MATCHER: &'static str =
     ":vis fragment specifier is experimental and subject to change";
 
-pub const EXPLAIN_LIFETIME_MATCHER: &'static str =
-    ":lifetime fragment specifier is experimental and subject to change";
-
 pub const EXPLAIN_LITERAL_MATCHER: &'static str =
     ":literal fragment specifier is experimental and subject to change";
 
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index d71527fd0ed..2b3930063f3 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -147,34 +147,37 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
             // as the outermost one, and the last as the innermost.
             false,
             |cx, span, old, self_f, other_fs| {
-        // match new {
-        //     Some(::std::cmp::Ordering::Equal) => old,
-        //     cmp => cmp
-        // }
+                // match new {
+                //     Some(::std::cmp::Ordering::Equal) => old,
+                //     cmp => cmp
+                // }
 
-        let new = {
-            let other_f = match (other_fs.len(), other_fs.get(0)) {
-                (1, Some(o_f)) => o_f,
-                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
-            };
+                let new = {
+                    let other_f = match (other_fs.len(), other_fs.get(0)) {
+                        (1, Some(o_f)) => o_f,
+                                _ => {
+                                    cx.span_bug(span,
+                                        "not exactly 2 arguments in `derive(PartialOrd)`")
+                                }
+                    };
 
-            let args = vec![
-                    cx.expr_addr_of(span, self_f),
-                    cx.expr_addr_of(span, other_f.clone()),
-                ];
+                    let args = vec![
+                            cx.expr_addr_of(span, self_f),
+                            cx.expr_addr_of(span, other_f.clone()),
+                        ];
 
-            cx.expr_call_global(span, partial_cmp_path.clone(), args)
-        };
+                    cx.expr_call_global(span, partial_cmp_path.clone(), args)
+                };
 
-        let eq_arm = cx.arm(span,
-                            vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))],
-                            old);
-        let neq_arm = cx.arm(span,
-                             vec![cx.pat_ident(span, test_id)],
-                             cx.expr_ident(span, test_id));
+                let eq_arm = cx.arm(span,
+                                    vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))],
+                                    old);
+                let neq_arm = cx.arm(span,
+                                    vec![cx.pat_ident(span, test_id)],
+                                    cx.expr_ident(span, test_id));
 
-        cx.expr_match(span, new, vec![eq_arm, neq_arm])
-    },
+                cx.expr_match(span, new, vec![eq_arm, neq_arm])
+            },
             equals_expr.clone(),
             Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
         if self_args.len() != 2 {
@@ -189,78 +192,99 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
 }
 
 /// Strict inequality.
-fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-    let strict_op = if less { BinOpKind::Lt } else { BinOpKind::Gt };
-    cs_fold1(false, // need foldr,
+fn cs_op(less: bool,
+         inclusive: bool,
+         cx: &mut ExtCtxt,
+         span: Span,
+         substr: &Substructure) -> P<Expr> {
+    let ordering_path = |cx: &mut ExtCtxt, name: &str| {
+        cx.expr_path(cx.path_global(span, cx.std_path(&["cmp", "Ordering", name])))
+    };
+
+    let par_cmp = |cx: &mut ExtCtxt, span, self_f: P<Expr>, other_fs: &[P<Expr>], default| {
+        let other_f = match (other_fs.len(), other_fs.get(0)) {
+            (1, Some(o_f)) => o_f,
+            _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
+        };
+
+        // `PartialOrd::partial_cmp(self.fi, other.fi)`
+        let cmp_path = cx.expr_path(cx.path_global(span, cx.std_path(&["cmp",
+                                                                       "PartialOrd",
+                                                                       "partial_cmp"])));
+        let cmp = cx.expr_call(span,
+                               cmp_path,
+                               vec![cx.expr_addr_of(span, self_f),
+                                    cx.expr_addr_of(span, other_f.clone())]);
+
+        let default = ordering_path(cx, default);
+        // `Option::unwrap_or(_, Ordering::Equal)`
+        let unwrap_path = cx.expr_path(cx.path_global(span, cx.std_path(&["option",
+                                                                          "Option",
+                                                                          "unwrap_or"])));
+        cx.expr_call(span, unwrap_path, vec![cmp, default])
+    };
+
+    let fold = cs_fold1(false, // need foldr
         |cx, span, subexpr, self_f, other_fs| {
-            // build up a series of chain ||'s and &&'s from the inside
+            // build up a series of `partial_cmp`s from the inside
             // out (hence foldr) to get lexical ordering, i.e. for op ==
             // `ast::lt`
             //
             // ```
-            // self.f1 < other.f1 || (!(other.f1 < self.f1) &&
-            // self.f2 < other.f2
+            // Ordering::then_with(
+            //    Option::unwrap_or(
+            //        PartialOrd::partial_cmp(self.f1, other.f1), Ordering::Equal)
+            //    ),
+            //    Option::unwrap_or(
+            //        PartialOrd::partial_cmp(self.f2, other.f2), Ordering::Greater)
+            //    )
             // )
+            // == Ordering::Less
             // ```
             //
             // and for op ==
             // `ast::le`
             //
             // ```
-            // self.f1 < other.f1 || (self.f1 == other.f1 &&
-            // self.f2 <= other.f2
+            // Ordering::then_with(
+            //    Option::unwrap_or(
+            //        PartialOrd::partial_cmp(self.f1, other.f1), Ordering::Equal)
+            //    ),
+            //    Option::unwrap_or(
+            //        PartialOrd::partial_cmp(self.f2, other.f2), Ordering::Greater)
+            //    )
             // )
+            // != Ordering::Greater
             // ```
             //
             // The optimiser should remove the redundancy. We explicitly
             // get use the binops to avoid auto-deref dereferencing too many
             // layers of pointers, if the type includes pointers.
-            //
-            let other_f = match (other_fs.len(), other_fs.get(0)) {
-                (1, Some(o_f)) => o_f,
-                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
-            };
 
-            let strict_ineq = cx.expr_binary(span, strict_op, self_f.clone(), other_f.clone());
+            // `Option::unwrap_or(PartialOrd::partial_cmp(self.fi, other.fi), Ordering::Equal)`
+            let par_cmp = par_cmp(cx, span, self_f, other_fs, "Equal");
 
-            let deleg_cmp = if !equal {
-                cx.expr_unary(span,
-                            ast::UnOp::Not,
-                            cx.expr_binary(span, strict_op, other_f.clone(), self_f))
-            } else {
-                cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone())
-            };
-
-            let and = cx.expr_binary(span, BinOpKind::And, deleg_cmp, subexpr);
-            cx.expr_binary(span, BinOpKind::Or, strict_ineq, and)
+            // `Ordering::then_with(Option::unwrap_or(..), ..)`
+            let then_with_path = cx.expr_path(cx.path_global(span,
+                                                             cx.std_path(&["cmp",
+                                                                           "Ordering",
+                                                                           "then_with"])));
+            cx.expr_call(span, then_with_path, vec![par_cmp, cx.lambda0(span, subexpr)])
         },
         |cx, args| {
             match args {
                 Some((span, self_f, other_fs)) => {
-                    // Special-case the base case to generate cleaner code with
-                    // fewer operations (e.g. `<=` instead of `<` and `==`).
-                    let other_f = match (other_fs.len(), other_fs.get(0)) {
-                        (1, Some(o_f)) => o_f,
-                        _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
-                    };
-
-                    let op = match (less, equal) {
-                        (false, false) => BinOpKind::Gt,
-                        (false, true) => BinOpKind::Ge,
-                        (true, false) => BinOpKind::Lt,
-                        (true, true) => BinOpKind::Le,
-                    };
-
-                    cx.expr_binary(span, op, self_f, other_f.clone())
-                }
-                None => cx.expr_bool(span, equal)
+                    let opposite = if less { "Greater" } else { "Less" };
+                    par_cmp(cx, span, self_f, other_fs, opposite)
+                },
+                None => cx.expr_bool(span, inclusive)
             }
         },
         Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
             } else {
-                let op = match (less, equal) {
+                let op = match (less, inclusive) {
                     (false, false) => GtOp,
                     (false, true) => GeOp,
                     (true, false) => LtOp,
@@ -271,5 +295,16 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substru
         }),
         cx,
         span,
-        substr)
+        substr);
+
+    match *substr.fields {
+        EnumMatching(.., ref all_fields) |
+        Struct(.., ref all_fields) if !all_fields.is_empty() => {
+            let ordering = ordering_path(cx, if less ^ inclusive { "Less" } else { "Greater" });
+            let comp_op = if inclusive { BinOpKind::Ne } else { BinOpKind::Eq };
+
+            cx.expr_binary(span, comp_op, fold, ordering)
+        }
+        _ => fold
+    }
 }
diff --git a/src/stdsimd b/src/stdsimd
-Subproject 2f86c75a2479cf051b92fc98273daaf7f151e7a
+Subproject a19ca1cd91cf97777af8268a6136bd2e4648e18
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs
new file mode 100644
index 00000000000..7d36517d970
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/issue_50493.rs
@@ -0,0 +1,32 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro, proc_macro_lib)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive)]
+pub fn derive(_: TokenStream) -> TokenStream {
+    let code = "
+        fn one(r: Restricted) {
+            r.field;
+        }
+        fn two(r: Restricted) {
+            r.field;
+        }
+    ";
+
+    code.parse().unwrap()
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs b/src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs
new file mode 100644
index 00000000000..51112f202c8
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/issue-50493.rs
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue_50493.rs
+// ignore-stage1
+
+#![feature(proc_macro)]
+
+#[macro_use]
+extern crate issue_50493;
+
+#[derive(Derive)] //~ ERROR field `field` of struct `Restricted` is private
+struct Restricted {
+    pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules
+}
+
+mod restricted {}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/coerce-to-bang.rs b/src/test/compile-fail/coerce-to-bang.rs
index 62ff09f4616..8b4e2c3c051 100644
--- a/src/test/compile-fail/coerce-to-bang.rs
+++ b/src/test/compile-fail/coerce-to-bang.rs
@@ -56,9 +56,8 @@ fn call_foo_f() {
 }
 
 fn array_a() {
-    // Accepted: return is coerced to `!` just fine, and then `22` can be
-    // because we already diverged.
-    let x: [!; 2] = [return, 22];
+    // Return is coerced to `!` just fine, but `22` cannot be.
+    let x: [!; 2] = [return, 22]; //~ ERROR mismatched types
 }
 
 fn array_b() {
diff --git a/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs b/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs
index dcf02f30830..a5df717e06b 100644
--- a/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs
+++ b/src/test/compile-fail/derives-span-PartialOrd-enum-struct-variant.rs
@@ -17,10 +17,6 @@ struct Error;
 enum Enum {
    A {
      x: Error //~ ERROR
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
    }
 }
 
diff --git a/src/test/compile-fail/derives-span-PartialOrd-enum.rs b/src/test/compile-fail/derives-span-PartialOrd-enum.rs
index 7eb44c7e19e..3411d2f3119 100644
--- a/src/test/compile-fail/derives-span-PartialOrd-enum.rs
+++ b/src/test/compile-fail/derives-span-PartialOrd-enum.rs
@@ -17,10 +17,6 @@ struct Error;
 enum Enum {
    A(
      Error //~ ERROR
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
      )
 }
 
diff --git a/src/test/compile-fail/derives-span-PartialOrd-struct.rs b/src/test/compile-fail/derives-span-PartialOrd-struct.rs
index 36dae0124ce..1feadc2fd83 100644
--- a/src/test/compile-fail/derives-span-PartialOrd-struct.rs
+++ b/src/test/compile-fail/derives-span-PartialOrd-struct.rs
@@ -16,10 +16,6 @@ struct Error;
 #[derive(PartialOrd,PartialEq)]
 struct Struct {
     x: Error //~ ERROR
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs b/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs
index fd2df096754..9db0fed2d9e 100644
--- a/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs
+++ b/src/test/compile-fail/derives-span-PartialOrd-tuple-struct.rs
@@ -16,10 +16,6 @@ struct Error;
 #[derive(PartialOrd,PartialEq)]
 struct Struct(
     Error //~ ERROR
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
 );
 
 fn main() {}
diff --git a/src/test/compile-fail/range_traits-1.rs b/src/test/compile-fail/range_traits-1.rs
index df766e361d5..32f9b83b6e2 100644
--- a/src/test/compile-fail/range_traits-1.rs
+++ b/src/test/compile-fail/range_traits-1.rs
@@ -15,35 +15,21 @@ struct AllTheRanges {
     a: Range<usize>,
     //~^ ERROR PartialOrd
     //~^^ ERROR Ord
-    //~^^^ ERROR binary operation `<` cannot be applied to type
-    //~^^^^ ERROR binary operation `>` cannot be applied to type
     b: RangeTo<usize>,
     //~^ ERROR PartialOrd
     //~^^ ERROR Ord
-    //~^^^ ERROR binary operation `<` cannot be applied to type
-    //~^^^^ ERROR binary operation `>` cannot be applied to type
     c: RangeFrom<usize>,
     //~^ ERROR PartialOrd
     //~^^ ERROR Ord
-    //~^^^ ERROR binary operation `<` cannot be applied to type
-    //~^^^^ ERROR binary operation `>` cannot be applied to type
     d: RangeFull,
     //~^ ERROR PartialOrd
     //~^^ ERROR Ord
-    //~^^^ ERROR binary operation `<` cannot be applied to type
-    //~^^^^ ERROR binary operation `>` cannot be applied to type
     e: RangeInclusive<usize>,
     //~^ ERROR PartialOrd
     //~^^ ERROR Ord
-    //~^^^ ERROR binary operation `<` cannot be applied to type
-    //~^^^^ ERROR binary operation `>` cannot be applied to type
     f: RangeToInclusive<usize>,
     //~^ ERROR PartialOrd
     //~^^ ERROR Ord
-    //~^^^ ERROR binary operation `<` cannot be applied to type
-    //~^^^^ ERROR binary operation `>` cannot be applied to type
-    //~^^^^^ ERROR binary operation `<=` cannot be applied to type
-    //~^^^^^^ ERROR binary operation `>=` cannot be applied to type
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gate-macro-lifetime-matcher.rs b/src/test/run-pass/issue-50731.rs
index 0d107d283cd..06df2b989af 100644
--- a/src/test/ui/feature-gate-macro-lifetime-matcher.rs
+++ b/src/test/run-pass/issue-50731.rs
@@ -1,4 +1,4 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,12 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher
-// feature gate is not used.
-
-macro_rules! m { ($lt:lifetime) => {} }
-//~^ ERROR :lifetime fragment specifier is experimental and subject to change
-
+enum Void {}
+fn foo(_: Result<(Void, u32), (Void, String)>) {}
 fn main() {
-    m!('a);
+    let _: fn(_) = foo;
 }
diff --git a/src/test/run-pass/macro-lifetime-used-with-bound.rs b/src/test/run-pass/macro-lifetime-used-with-bound.rs
index b0c9280b6ce..b9e1fde6b1f 100644
--- a/src/test/run-pass/macro-lifetime-used-with-bound.rs
+++ b/src/test/run-pass/macro-lifetime-used-with-bound.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(macro_lifetime_matcher)]
-
 macro_rules! foo {
     ($l:lifetime, $l2:lifetime) => {
         fn f<$l: $l2, $l2>(arg: &$l str, arg2: &$l2 str) -> &$l str {
diff --git a/src/test/run-pass/macro-lifetime-used-with-labels.rs b/src/test/run-pass/macro-lifetime-used-with-labels.rs
index 8a2d76e17df..d003d7dcfb6 100644
--- a/src/test/run-pass/macro-lifetime-used-with-labels.rs
+++ b/src/test/run-pass/macro-lifetime-used-with-labels.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![allow(unreachable_code)]
-#![feature(macro_lifetime_matcher)]
 
 macro_rules! x {
     ($a:lifetime) => {
diff --git a/src/test/run-pass/macro-lifetime-used-with-static.rs b/src/test/run-pass/macro-lifetime-used-with-static.rs
index 468ee2e9436..5c1f8683e00 100644
--- a/src/test/run-pass/macro-lifetime-used-with-static.rs
+++ b/src/test/run-pass/macro-lifetime-used-with-static.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(macro_lifetime_matcher)]
-
 macro_rules! foo {
     ($l:lifetime) => {
         fn f(arg: &$l str) -> &$l str {
diff --git a/src/test/run-pass/macro-lifetime.rs b/src/test/run-pass/macro-lifetime.rs
index db521ca7f10..ff5798ff78d 100644
--- a/src/test/run-pass/macro-lifetime.rs
+++ b/src/test/run-pass/macro-lifetime.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(macro_lifetime_matcher)]
-
 macro_rules! foo {
     ($l:lifetime) => {
         fn f<$l>(arg: &$l str) -> &$l str {
diff --git a/src/test/rustdoc-js/deduplication.js b/src/test/rustdoc-js/deduplication.js
new file mode 100644
index 00000000000..0f29607d5c9
--- /dev/null
+++ b/src/test/rustdoc-js/deduplication.js
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-order
+
+const QUERY = 'is_nan';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::f32', 'name': 'is_nan' },
+        { 'path': 'std::f64', 'name': 'is_nan' },
+        { 'path': 'std::option::Option', 'name': 'is_none' },
+    ],
+};
diff --git a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr b/src/test/ui/feature-gate-macro-lifetime-matcher.stderr
deleted file mode 100644
index b7805f6f5fb..00000000000
--- a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: :lifetime fragment specifier is experimental and subject to change (see issue #46895)
-  --> $DIR/feature-gate-macro-lifetime-matcher.rs:14:19
-   |
-LL | macro_rules! m { ($lt:lifetime) => {} }
-   |                   ^^^^^^^^^^^^
-   |
-   = help: add #![feature(macro_lifetime_matcher)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/macros/nonterminal-matching.rs b/src/test/ui/macros/nonterminal-matching.rs
index 4dcb8afa94e..54d280a63e7 100644
--- a/src/test/ui/macros/nonterminal-matching.rs
+++ b/src/test/ui/macros/nonterminal-matching.rs
@@ -11,7 +11,7 @@
 // Check that we are refusing to match on complex nonterminals for which tokens are
 // unavailable and we'd have to go through AST comparisons.
 
-#![feature(decl_macro, macro_lifetime_matcher)]
+#![feature(decl_macro)]
 
 macro simple_nonterminal($nt_ident: ident, $nt_lifetime: lifetime, $nt_tt: tt) {
     macro n(a $nt_ident b $nt_lifetime c $nt_tt d) {
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 7a4c00c669b3bf0ffb24c7aa89a776cd48f1e2d
+Subproject c658fc8cbcd1f199edd445a49cb43139ebdc5f0
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 25f7a2d1294..47667d93cb7 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -160,10 +160,11 @@ function main(argv) {
     // execQuery first parameter is built in getQuery (which takes in the search input).
     // execQuery last parameter is built in buildIndex.
     // buildIndex requires the hashmap from search-index.
-    var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery",
-                           "execSearch"];
+    var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
+                           "getQuery", "buildIndex", "execQuery", "execSearch"];
 
     finalJS += 'window = { "currentCrate": "std" };\n';
+    finalJS += 'var rootPath = "../";\n';
     finalJS += ALIASES;
     finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
     finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs);