diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 984358396ab2a..1ccfca8d0d5ff 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -386,6 +386,35 @@ function initSearch(rawSearchIndex) {
         if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
             throw ["You cannot have more than one element if you use quotes"];
         }
+        const typeFilter = parserState.typeFilter;
+        parserState.typeFilter = null;
+        if (name === "!") {
+            if (typeFilter !== null && typeFilter !== "primitive") {
+                throw [
+                    "Invalid search type: primitive never type ",
+                    "!",
+                    " and ",
+                    typeFilter,
+                    " both specified",
+                ];
+            }
+            if (generics.length !== 0) {
+                throw [
+                    "Never type ",
+                    "!",
+                    " does not accept generic parameters",
+                ];
+            }
+            return {
+                name: "never",
+                id: -1,
+                fullPath: ["never"],
+                pathWithoutLast: [],
+                pathLast: "never",
+                generics: [],
+                typeFilter: "primitive",
+            };
+        }
         const pathSegments = name.split("::");
         if (pathSegments.length > 1) {
             for (let i = 0, len = pathSegments.length; i < len; ++i) {
@@ -399,6 +428,13 @@ function initSearch(rawSearchIndex) {
                     }
                     throw ["Unexpected ", "::::"];
                 }
+
+                if (pathSegment === "!") {
+                    pathSegments[i] = "never";
+                    if (i !== 0) {
+                        throw ["Never type ", "!", " is not associated item"];
+                    }
+                }
             }
         }
         // In case we only have something like `<p>`, there is no name.
@@ -409,8 +445,6 @@ function initSearch(rawSearchIndex) {
         if (isInGenerics) {
             parserState.genericsElems += 1;
         }
-        const typeFilter = parserState.typeFilter;
-        parserState.typeFilter = null;
         return {
             name: name,
             id: -1,
@@ -459,10 +493,11 @@ function initSearch(rawSearchIndex) {
                         break;
                     }
                     if (foundExclamation !== -1) {
-                        if (start <= (end - 2)) {
+                        if (foundExclamation !== start &&
+                            isIdentCharacter(parserState.userQuery[foundExclamation - 1])
+                        ) {
                             throw ["Cannot have associated items in macros"];
                         } else {
-                            // if start == end - 1, we got the never type
                             // while the never type has no associated macros, we still
                             // can parse a path like that
                             foundExclamation = -1;
@@ -478,7 +513,10 @@ function initSearch(rawSearchIndex) {
             end = parserState.pos;
         }
         // if start == end - 1, we got the never type
-        if (foundExclamation !== -1 && start <= (end - 2)) {
+        if (foundExclamation !== -1 &&
+            foundExclamation !== start &&
+            isIdentCharacter(parserState.userQuery[foundExclamation - 1])
+        ) {
             if (parserState.typeFilter === null) {
                 parserState.typeFilter = "macro";
             } else if (parserState.typeFilter !== "macro") {
diff --git a/tests/rustdoc-js-std/never.js b/tests/rustdoc-js-std/never.js
index ed3776b3c2ae0..27d415b5e486d 100644
--- a/tests/rustdoc-js-std/never.js
+++ b/tests/rustdoc-js-std/never.js
@@ -1,6 +1,14 @@
-const EXPECTED = {
-    'query': '!',
-    'others': [
-        { 'path': 'std', 'name': 'never' },
-    ],
-};
+const EXPECTED = [
+    {
+        'query': '!',
+        'others': [
+            { 'path': 'std', 'name': 'never' },
+        ],
+    },
+    {
+        'query': '!::clone',
+        'others': [
+            { 'path': 'std::never', 'name': 'clone' },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index aa8ee86d67247..af7f63f99cbdf 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -359,6 +359,15 @@ const PARSED = [
         userQuery: "mod:a!",
         error: 'Invalid search type: macro `!` and `mod` both specified',
     },
+    {
+        query: "mod:!",
+        elems: [],
+        foundElems: 0,
+        original: "mod:!",
+        returned: [],
+        userQuery: "mod:!",
+        error: 'Invalid search type: primitive never type `!` and `mod` both specified',
+    },
     {
         query: "a!::a",
         elems: [],
diff --git a/tests/rustdoc-js-std/parser-ident.js b/tests/rustdoc-js-std/parser-ident.js
index d9ee5fb564b68..f65a7ce6692b0 100644
--- a/tests/rustdoc-js-std/parser-ident.js
+++ b/tests/rustdoc-js-std/parser-ident.js
@@ -8,11 +8,12 @@ const PARSED = [
             pathLast: "r",
             generics: [
                 {
-                    name: "!",
-                    fullPath: ["!"],
+                    name: "never",
+                    fullPath: ["never"],
                     pathWithoutLast: [],
-                    pathLast: "!",
+                    pathLast: "never",
                     generics: [],
+                    typeFilter: 15,
                 },
             ],
             typeFilter: -1,
@@ -26,12 +27,12 @@ const PARSED = [
     {
         query: "!",
         elems: [{
-            name: "!",
-            fullPath: ["!"],
+            name: "never",
+            fullPath: ["never"],
             pathWithoutLast: [],
-            pathLast: "!",
+            pathLast: "never",
             generics: [],
-            typeFilter: -1,
+            typeFilter: 15,
         }],
         foundElems: 1,
         original: "!",
@@ -64,12 +65,21 @@ const PARSED = [
         userQuery: "a!::b",
         error: "Cannot have associated items in macros",
     },
+    {
+        query: "!<T>",
+        elems: [],
+        foundElems: 0,
+        original: "!<T>",
+        returned: [],
+        userQuery: "!<t>",
+        error: "Never type `!` does not accept generic parameters",
+    },
     {
         query: "!::b",
         elems: [{
             name: "!::b",
-            fullPath: ["!", "b"],
-            pathWithoutLast: ["!"],
+            fullPath: ["never", "b"],
+            pathWithoutLast: ["never"],
             pathLast: "b",
             generics: [],
             typeFilter: -1,
@@ -80,6 +90,58 @@ const PARSED = [
         userQuery: "!::b",
         error: null,
     },
+    {
+        query: "b::!",
+        elems: [],
+        foundElems: 0,
+        original: "b::!",
+        returned: [],
+        userQuery: "b::!",
+        error: "Never type `!` is not associated item",
+    },
+    {
+        query: "!::!",
+        elems: [],
+        foundElems: 0,
+        original: "!::!",
+        returned: [],
+        userQuery: "!::!",
+        error: "Never type `!` is not associated item",
+    },
+    {
+        query: "b::!::c",
+        elems: [],
+        foundElems: 0,
+        original: "b::!::c",
+        returned: [],
+        userQuery: "b::!::c",
+        error: "Never type `!` is not associated item",
+    },
+    {
+        query: "!::b<T>",
+        elems: [{
+            name: "!::b",
+            fullPath: ["never", "b"],
+            pathWithoutLast: ["never"],
+            pathLast: "b",
+            generics: [
+                {
+                    name: "t",
+                    fullPath: ["t"],
+                    pathWithoutLast: [],
+                    pathLast: "t",
+                    generics: [],
+                    typeFilter: -1,
+                }
+            ],
+            typeFilter: -1,
+        }],
+        foundElems: 1,
+        original: "!::b<T>",
+        returned: [],
+        userQuery: "!::b<t>",
+        error: null,
+    },
     {
         query: "a!::b!",
         elems: [],
diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js
index 665e2a9b2e3d7..6ea86609115bf 100644
--- a/tests/rustdoc-js-std/parser-returned.js
+++ b/tests/rustdoc-js-std/parser-returned.js
@@ -84,12 +84,12 @@ const PARSED = [
         foundElems: 1,
         original: "-> !",
         returned: [{
-            name: "!",
-            fullPath: ["!"],
+            name: "never",
+            fullPath: ["never"],
             pathWithoutLast: [],
-            pathLast: "!",
+            pathLast: "never",
             generics: [],
-            typeFilter: -1,
+            typeFilter: 15,
         }],
         userQuery: "-> !",
         error: null,
diff --git a/tests/rustdoc-js/never-search.js b/tests/rustdoc-js/never-search.js
new file mode 100644
index 0000000000000..ed24d693133ba
--- /dev/null
+++ b/tests/rustdoc-js/never-search.js
@@ -0,0 +1,46 @@
+// exact-check
+
+const EXPECTED = [
+    {
+        'query': '-> !',
+        'others': [
+            { 'path': 'never_search', 'name': 'loops' },
+        ],
+    },
+    {
+        'query': '-> never',
+        'others': [
+            { 'path': 'never_search', 'name': 'loops' },
+            { 'path': 'never_search', 'name': 'returns' },
+        ],
+    },
+    {
+        'query': '!',
+        'in_args': [
+            { 'path': 'never_search', 'name': 'impossible' },
+            { 'path': 'never_search', 'name': 'box_impossible' },
+        ],
+    },
+    {
+        'query': 'never',
+        'in_args': [
+            { 'path': 'never_search', 'name': 'impossible' },
+            { 'path': 'never_search', 'name': 'uninteresting' },
+            { 'path': 'never_search', 'name': 'box_impossible' },
+            { 'path': 'never_search', 'name': 'box_uninteresting' },
+        ],
+    },
+    {
+        'query': 'box<!>',
+        'in_args': [
+            { 'path': 'never_search', 'name': 'box_impossible' },
+        ],
+    },
+    {
+        'query': 'box<never>',
+        'in_args': [
+            { 'path': 'never_search', 'name': 'box_impossible' },
+            { 'path': 'never_search', 'name': 'box_uninteresting' },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/never-search.rs b/tests/rustdoc-js/never-search.rs
new file mode 100644
index 0000000000000..299b4660dae9e
--- /dev/null
+++ b/tests/rustdoc-js/never-search.rs
@@ -0,0 +1,13 @@
+#![feature(never_type)]
+
+#[allow(nonstandard_style)]
+pub struct never;
+
+pub fn loops() -> ! { loop {} }
+pub fn returns() -> never { never }
+
+pub fn impossible(x: !) { match x {} }
+pub fn uninteresting(x: never) { match x { never => {} } }
+
+pub fn box_impossible(x: Box<!>) { match *x {} }
+pub fn box_uninteresting(x: Box<never>) { match *x { never => {} } }