Exclude "test" from doc_auto_cfg rendering
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index dfee2b7..2c1dcad 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -43,15 +43,81 @@
 
 impl Cfg {
     /// Parses a `NestedMetaItem` into a `Cfg`.
-    fn parse_nested(nested_cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> {
+    fn parse_nested(
+        nested_cfg: &NestedMetaItem,
+        exclude: &[Symbol],
+    ) -> Result<Option<Cfg>, InvalidCfgError> {
         match nested_cfg {
-            NestedMetaItem::MetaItem(ref cfg) => Cfg::parse(cfg),
+            NestedMetaItem::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude),
             NestedMetaItem::Literal(ref lit) => {
                 Err(InvalidCfgError { msg: "unexpected literal", span: lit.span })
             }
         }
     }
 
+    crate fn parse_without(
+        cfg: &MetaItem,
+        exclude: &[Symbol],
+    ) -> Result<Option<Cfg>, InvalidCfgError> {
+        let name = match cfg.ident() {
+            Some(ident) => ident.name,
+            None => {
+                return Err(InvalidCfgError {
+                    msg: "expected a single identifier",
+                    span: cfg.span,
+                });
+            }
+        };
+        match cfg.kind {
+            MetaItemKind::Word => {
+                if exclude.contains(&name) {
+                    Ok(None)
+                } else {
+                    Ok(Some(Cfg::Cfg(name, None)))
+                }
+            }
+            MetaItemKind::NameValue(ref lit) => match lit.kind {
+                LitKind::Str(value, _) => {
+                    if exclude.contains(&name) {
+                        Ok(None)
+                    } else {
+                        Ok(Some(Cfg::Cfg(name, Some(value))))
+                    }
+                }
+                _ => Err(InvalidCfgError {
+                    // FIXME: if the main #[cfg] syntax decided to support non-string literals,
+                    // this should be changed as well.
+                    msg: "value of cfg option should be a string literal",
+                    span: lit.span,
+                }),
+            },
+            MetaItemKind::List(ref items) => {
+                let sub_cfgs = items.iter().filter_map(|i| match Cfg::parse_nested(i, exclude) {
+                    Ok(Some(c)) => Some(Ok(c)),
+                    Err(e) => Some(Err(e)),
+                    _ => None,
+                });
+                let ret = match name {
+                    sym::all => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)),
+                    sym::any => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)),
+                    sym::not => {
+                        let mut sub_cfgs = sub_cfgs.collect::<Vec<_>>();
+                        if sub_cfgs.len() == 1 {
+                            Ok(!sub_cfgs.pop().unwrap()?)
+                        } else {
+                            Err(InvalidCfgError { msg: "expected 1 cfg-pattern", span: cfg.span })
+                        }
+                    }
+                    _ => Err(InvalidCfgError { msg: "invalid predicate", span: cfg.span }),
+                };
+                match ret {
+                    Ok(c) => Ok(Some(c)),
+                    Err(e) => Err(e),
+                }
+            }
+        }
+    }
+
     /// Parses a `MetaItem` into a `Cfg`.
     ///
     /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or
@@ -60,42 +126,7 @@ fn parse_nested(nested_cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> {
     /// If the content is not properly formatted, it will return an error indicating what and where
     /// the error is.
     crate fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
-        let name = match cfg.ident() {
-            Some(ident) => ident.name,
-            None => {
-                return Err(InvalidCfgError {
-                    msg: "expected a single identifier",
-                    span: cfg.span,
-                });
-            }
-        };
-        match cfg.kind {
-            MetaItemKind::Word => Ok(Cfg::Cfg(name, None)),
-            MetaItemKind::NameValue(ref lit) => match lit.kind {
-                LitKind::Str(value, _) => Ok(Cfg::Cfg(name, Some(value))),
-                _ => Err(InvalidCfgError {
-                    // FIXME: if the main #[cfg] syntax decided to support non-string literals,
-                    // this should be changed as well.
-                    msg: "value of cfg option should be a string literal",
-                    span: lit.span,
-                }),
-            },
-            MetaItemKind::List(ref items) => {
-                let mut sub_cfgs = items.iter().map(Cfg::parse_nested);
-                match name {
-                    sym::all => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)),
-                    sym::any => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)),
-                    sym::not => {
-                        if sub_cfgs.len() == 1 {
-                            Ok(!sub_cfgs.next().unwrap()?)
-                        } else {
-                            Err(InvalidCfgError { msg: "expected 1 cfg-pattern", span: cfg.span })
-                        }
-                    }
-                    _ => Err(InvalidCfgError { msg: "invalid predicate", span: cfg.span }),
-                }
-            }
-        }
+        Self::parse_without(cfg, &[]).map(|ret| ret.unwrap())
     }
 
     /// Checks whether the given configuration can be matched in the current session.
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index fac1a08..347f9d0 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -831,7 +831,10 @@ fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
                 self.iter()
                     .filter(|attr| attr.has_name(sym::cfg))
                     .filter_map(|attr| single(attr.meta_item_list()?))
-                    .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
+                    .filter_map(|attr| match Cfg::parse_without(attr.meta_item()?, &[sym::test]) {
+                        Ok(Some(c)) => Some(c),
+                        _ => None,
+                    })
                     .filter(|cfg| !hidden_cfg.contains(cfg))
                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
             } else {