diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs
index d438fe35ff488..62ba412cb4192 100644
--- a/src/librustc_passes/check_attr.rs
+++ b/src/librustc_passes/check_attr.rs
@@ -70,7 +70,7 @@ impl CheckAttrVisitor<'tcx> {
             } else if self.tcx.sess.check_name(attr, sym::track_caller) {
                 self.check_track_caller(&attr.span, attrs, span, target)
             } else if self.tcx.sess.check_name(attr, sym::doc) {
-                self.check_doc_alias(attr)
+                self.check_doc_alias(attr, hir_id, target)
             } else {
                 true
             };
@@ -217,7 +217,7 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_doc_alias(&self, attr: &Attribute) -> bool {
+    fn check_doc_alias(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
         if let Some(mi) = attr.meta() {
             if let Some(list) = mi.meta_item_list() {
                 for meta in list {
@@ -238,6 +238,28 @@ impl CheckAttrVisitor<'tcx> {
                                 .emit();
                             return false;
                         }
+                        if let Some(err) = match target {
+                            Target::Impl => Some("implementation block"),
+                            Target::ForeignMod => Some("extern block"),
+                            Target::AssocTy => {
+                                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+                                let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+                                if Target::from_item(containing_item) == Target::Impl {
+                                    Some("type alias in implementation block")
+                                } else {
+                                    None
+                                }
+                            }
+                            _ => None,
+                        } {
+                            self.tcx
+                                .sess
+                                .struct_span_err(
+                                    meta.span(),
+                                    &format!("`#[doc(alias = \"...\")]` isn't allowed on {}", err,),
+                                )
+                                .emit();
+                        }
                     }
                 }
             }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b13acaae1bf23..f7c6a18a0e896 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -470,6 +470,10 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                 sess.time("missing_docs", || {
                     rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
                 });
+                for &module in tcx.hir().krate().modules.keys() {
+                    let local_def_id = tcx.hir().local_def_id(module);
+                    tcx.ensure().check_mod_attrs(local_def_id);
+                }
 
                 let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
                 // Convert from a HirId set to a DefId set since we don't always have easy access
diff --git a/src/test/rustdoc-js/doc-alias.js b/src/test/rustdoc-js/doc-alias.js
index 896808d415780..ff188d5145801 100644
--- a/src/test/rustdoc-js/doc-alias.js
+++ b/src/test/rustdoc-js/doc-alias.js
@@ -5,7 +5,7 @@ const QUERY = [
     'StructFieldItem',
     'StructMethodItem',
     'ImplTraitItem',
-    'ImplAssociatedConstItem',
+    'StructImplConstItem',
     'ImplTraitFunction',
     'EnumItem',
     'VariantItem',
@@ -64,8 +64,16 @@ const EXPECTED = [
         'others': [],
     },
     {
-        // ImplAssociatedConstItem
-        'others': [],
+        // StructImplConstItem
+        'others': [
+            {
+                'path': 'doc_alias::Struct',
+                'name': 'ImplConstItem',
+                'alias': 'StructImplConstItem',
+                'href': '../doc_alias/struct.Struct.html#associatedconstant.ImplConstItem',
+                'is_alias': true
+            },
+        ],
     },
     {
         'others': [
@@ -197,6 +205,10 @@ const EXPECTED = [
                 'href': '../doc_alias/constant.Const.html',
                 'is_alias': true
             },
+            {
+                'path': 'doc_alias::Struct',
+                'name': 'ImplConstItem',
+            },
         ],
     },
     {
diff --git a/src/test/rustdoc-js/doc-alias.rs b/src/test/rustdoc-js/doc-alias.rs
index 84c638a199507..41caa98643cdd 100644
--- a/src/test/rustdoc-js/doc-alias.rs
+++ b/src/test/rustdoc-js/doc-alias.rs
@@ -7,16 +7,14 @@ pub struct Struct {
 }
 
 impl Struct {
+    #[doc(alias = "StructImplConstItem")]
+    pub const ImplConstItem: i32 = 0;
     #[doc(alias = "StructMethodItem")]
     pub fn method(&self) {}
 }
 
 impl Trait for Struct {
-    // Shouldn't be listed in aliases!
-    #[doc(alias = "ImplTraitItem")]
     type Target = u32;
-    // Shouldn't be listed in aliases!
-    #[doc(alias = "ImplAssociatedConstItem")]
     const AssociatedConst: i32 = 12;
 
     #[doc(alias = "ImplTraitFunction")]
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr-location.rs b/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
new file mode 100644
index 0000000000000..545964c7bd61b
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr-location.rs
@@ -0,0 +1,23 @@
+#![feature(doc_alias)]
+
+pub struct Bar;
+pub trait Foo {
+    type X;
+    fn foo() -> Self::X;
+}
+
+#[doc(alias = "foo")] //~ ERROR
+extern {}
+
+#[doc(alias = "bar")] //~ ERROR
+impl Bar {
+    #[doc(alias = "const")]
+    pub const A: u32 = 0;
+}
+
+#[doc(alias = "foobar")] //~ ERROR
+impl Foo for Bar {
+    #[doc(alias = "assoc")] //~ ERROR
+    type X = i32;
+    fn foo() -> Self::X { 0 }
+}
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr-location.stderr b/src/test/rustdoc-ui/check-doc-alias-attr-location.stderr
new file mode 100644
index 0000000000000..a66e9939eaf18
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr-location.stderr
@@ -0,0 +1,26 @@
+error: `#[doc(alias = "...")]` isn't allowed on extern block
+  --> $DIR/check-doc-alias-attr-location.rs:9:7
+   |
+LL | #[doc(alias = "foo")]
+   |       ^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
+  --> $DIR/check-doc-alias-attr-location.rs:12:7
+   |
+LL | #[doc(alias = "bar")]
+   |       ^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
+  --> $DIR/check-doc-alias-attr-location.rs:18:7
+   |
+LL | #[doc(alias = "foobar")]
+   |       ^^^^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
+  --> $DIR/check-doc-alias-attr-location.rs:20:11
+   |
+LL |     #[doc(alias = "assoc")]
+   |           ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.rs b/src/test/rustdoc-ui/check-doc-alias-attr.rs
new file mode 100644
index 0000000000000..b02cc1a4545b1
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+#![feature(doc_alias)]
+
+#[doc(alias = "foo")] // ok!
+pub struct Bar;
+
+#[doc(alias)] //~ ERROR
+#[doc(alias = 0)] //~ ERROR
+#[doc(alias("bar"))] //~ ERROR
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/rustdoc-ui/check-doc-alias-attr.stderr
new file mode 100644
index 0000000000000..268230ab44a0a
--- /dev/null
+++ b/src/test/rustdoc-ui/check-doc-alias-attr.stderr
@@ -0,0 +1,20 @@
+error: doc alias attribute expects a string: #[doc(alias = "0")]
+  --> $DIR/check-doc-alias-attr.rs:7:7
+   |
+LL | #[doc(alias)]
+   |       ^^^^^
+
+error: doc alias attribute expects a string: #[doc(alias = "0")]
+  --> $DIR/check-doc-alias-attr.rs:8:7
+   |
+LL | #[doc(alias = 0)]
+   |       ^^^^^^^^^
+
+error: doc alias attribute expects a string: #[doc(alias = "0")]
+  --> $DIR/check-doc-alias-attr.rs:9:7
+   |
+LL | #[doc(alias("bar"))]
+   |       ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/check-doc-alias-attr-location.rs b/src/test/ui/check-doc-alias-attr-location.rs
new file mode 100644
index 0000000000000..dac9b7372e08b
--- /dev/null
+++ b/src/test/ui/check-doc-alias-attr-location.rs
@@ -0,0 +1,24 @@
+#![crate_type="lib"]
+#![feature(doc_alias)]
+
+pub struct Bar;
+pub trait Foo {
+    type X;
+    fn foo() -> Self::X;
+}
+
+#[doc(alias = "foo")] //~ ERROR
+extern {}
+
+#[doc(alias = "bar")] //~ ERROR
+impl Bar {
+    #[doc(alias = "const")]
+    const A: u32 = 0;
+}
+
+#[doc(alias = "foobar")] //~ ERROR
+impl Foo for Bar {
+    #[doc(alias = "assoc")] //~ ERROR
+    type X = i32;
+    fn foo() -> Self::X { 0 }
+}
diff --git a/src/test/ui/check-doc-alias-attr-location.stderr b/src/test/ui/check-doc-alias-attr-location.stderr
new file mode 100644
index 0000000000000..29a99e4470e5f
--- /dev/null
+++ b/src/test/ui/check-doc-alias-attr-location.stderr
@@ -0,0 +1,26 @@
+error: `#[doc(alias = "...")]` isn't allowed on extern block
+  --> $DIR/check-doc-alias-attr-location.rs:10:7
+   |
+LL | #[doc(alias = "foo")]
+   |       ^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
+  --> $DIR/check-doc-alias-attr-location.rs:13:7
+   |
+LL | #[doc(alias = "bar")]
+   |       ^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
+  --> $DIR/check-doc-alias-attr-location.rs:19:7
+   |
+LL | #[doc(alias = "foobar")]
+   |       ^^^^^^^^^^^^^^^^
+
+error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
+  --> $DIR/check-doc-alias-attr-location.rs:21:11
+   |
+LL |     #[doc(alias = "assoc")]
+   |           ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+