about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWim Looman <git@nemo157.com>2020-11-03 19:45:16 +0100
committerGuillaume Gomez <guillaume.gomez@huawei.com>2021-10-05 17:25:44 +0200
commit10cdbd847fd00d093ce89a4fffde5d90c8bb9817 (patch)
tree565637fa1346110af2b1b1aa415cd1d1b2fe025a
parent074f63648bd2368d5ca19aed02b5763a144e5d05 (diff)
downloadrust-10cdbd847fd00d093ce89a4fffde5d90c8bb9817.tar.gz
rust-10cdbd847fd00d093ce89a4fffde5d90c8bb9817.zip
Make cfg implicitly imply doc(cfg)
This is only active when the `doc_cfg` feature is active.

The implicit cfg can be overridden via #[doc(cfg(...))], so e.g. to
hide a #[cfg] you can use something like:

```rust
 #[cfg(unix)]
 #[doc(cfg(all()))]
pub struct Unix;
```

(since `all()` is always true, it is never shown in the docs)
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs52
-rw-r--r--src/librustdoc/doctest.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs2
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/test/rustdoc/doc-cfg-implicit-gate.rs7
-rw-r--r--src/test/rustdoc/doc-cfg-implicit.rs31
8 files changed, 92 insertions, 9 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4a888b22332..39493f6edf8 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -318,10 +318,10 @@ fn merge_attrs(
             } else {
                 Attributes::from_ast(&both, None)
             },
-            both.cfg(cx.sess()),
+            both.cfg(cx.tcx),
         )
     } else {
-        (old_attrs.clean(cx), old_attrs.cfg(cx.sess()))
+        (old_attrs.clean(cx), old_attrs.cfg(cx.tcx))
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a55d85f5841..41bc30fd398 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1973,7 +1973,7 @@ fn clean_extern_crate(
         def_id: crate_def_id.into(),
         visibility: krate.vis.clean(cx),
         kind: box ExternCrateItem { src: orig_name },
-        cfg: attrs.cfg(cx.sess()),
+        cfg: attrs.cfg(cx.tcx),
     }]
 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0e78fe7aec3..288644ff296 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -421,7 +421,7 @@ impl Item {
             kind,
             box ast_attrs.clean(cx),
             cx,
-            ast_attrs.cfg(cx.sess()),
+            ast_attrs.cfg(cx.tcx),
         )
     }
 
@@ -747,7 +747,7 @@ crate trait AttributesExt {
 
     fn other_attrs(&self) -> Vec<ast::Attribute>;
 
-    fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
+    fn cfg(&self, tcx: TyCtxt<'_>) -> Option<Arc<Cfg>>;
 }
 
 impl AttributesExt for [ast::Attribute] {
@@ -772,8 +772,52 @@ impl AttributesExt for [ast::Attribute] {
         self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
     }
 
-    fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
-        let mut cfg = Cfg::True;
+    fn cfg(&self, tcx: TyCtxt<'_>) -> Option<Arc<Cfg>> {
+        let sess = tcx.sess;
+        let doc_cfg_active = tcx.features().doc_cfg;
+
+        trait SingleExt {
+            type Item;
+            fn single(self) -> Option<Self::Item>;
+        }
+
+        impl<T: IntoIterator> SingleExt for T {
+            type Item = T::Item;
+            fn single(self) -> Option<Self::Item> {
+                let mut iter = self.into_iter();
+                let item = iter.next()?;
+                iter.next().is_none().then_some(())?;
+                Some(item)
+            }
+        }
+
+        let mut cfg = if doc_cfg_active {
+            let mut doc_cfg = self
+                .iter()
+                .filter(|attr| attr.has_name(sym::doc))
+                .filter_map(|attr| Some(attr.meta_item_list()?.single()?))
+                .filter(|attr| attr.has_name(sym::cfg))
+                .filter_map(|attr| Some(attr.meta_item_list()?.single()?.meta_item()?.clone()))
+                .peekable();
+            if doc_cfg.peek().is_some() {
+                doc_cfg
+                    .filter_map(|attr| {
+                        Cfg::parse(&attr).map_err(|e| sess.diagnostic().span_err(e.span, e.msg)).ok()
+                    })
+                    .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
+            } else {
+                self
+                    .iter()
+                    .filter(|attr| attr.has_name(sym::cfg))
+                    .filter_map(|attr| Some(attr.meta_item_list()?.single()?.meta_item()?.clone()))
+                    .filter_map(|attr| {
+                        Cfg::parse(&attr).map_err(|e| sess.diagnostic().span_err(e.span, e.msg)).ok()
+                    })
+                    .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
+            }
+        } else {
+            Cfg::True
+        };
 
         for attr in self.iter() {
             // #[doc]
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 43abcf095d8..8cf7b50fbd9 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1123,7 +1123,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
         let ast_attrs = self.tcx.hir().attrs(hir_id);
         let mut attrs = Attributes::from_ast(ast_attrs, None);
 
-        if let Some(ref cfg) = ast_attrs.cfg(self.sess) {
+        if let Some(ref cfg) = ast_attrs.cfg(self.tcx) {
             if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
                 return;
             }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 28b2eded7cc..e68e1223171 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -323,7 +323,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                     let import_item = clean::Item {
                         def_id: import_def_id.into(),
                         attrs: import_attrs,
-                        cfg: ast_attrs.cfg(cx.sess()),
+                        cfg: ast_attrs.cfg(cx.tcx()),
                         ..myitem.clone()
                     };
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index efc8e31498a..d070ce22890 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -5,6 +5,7 @@
 #![feature(rustc_private)]
 #![feature(array_methods)]
 #![feature(assert_matches)]
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
diff --git a/src/test/rustdoc/doc-cfg-implicit-gate.rs b/src/test/rustdoc/doc-cfg-implicit-gate.rs
new file mode 100644
index 00000000000..92804d3729b
--- /dev/null
+++ b/src/test/rustdoc/doc-cfg-implicit-gate.rs
@@ -0,0 +1,7 @@
+// compile-flags:--cfg feature="worricow"
+#![crate_name = "xenogenous"]
+
+// @has 'xenogenous/struct.Worricow.html'
+// @count   - '//*[@class="stab portability"]' 0
+#[cfg(feature = "worricow")]
+pub struct Worricow;
diff --git a/src/test/rustdoc/doc-cfg-implicit.rs b/src/test/rustdoc/doc-cfg-implicit.rs
new file mode 100644
index 00000000000..36c2025785d
--- /dev/null
+++ b/src/test/rustdoc/doc-cfg-implicit.rs
@@ -0,0 +1,31 @@
+#![crate_name = "funambulism"]
+#![feature(doc_cfg)]
+
+// @has 'funambulism/struct.Disorbed.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature disorbed'
+// compile-flags:--cfg feature="disorbed"
+#[cfg(feature = "disorbed")]
+pub struct Disorbed;
+
+// @has 'funambulism/struct.Aesthesia.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature aesthesia'
+// compile-flags:--cfg feature="aesthesia"
+#[doc(cfg(feature = "aesthesia"))]
+pub struct Aesthesia;
+
+// @has 'funambulism/struct.Pliothermic.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature pliothermic'
+// compile-flags:--cfg feature="epopoeist"
+#[cfg(feature = "epopoeist")]
+#[doc(cfg(feature = "pliothermic"))]
+pub struct Pliothermic;
+
+// @has 'funambulism/struct.Simillimum.html'
+// @count   - '//*[@class="stab portability"]' 0
+// compile-flags:--cfg feature="simillimum"
+#[cfg(feature = "simillimum")]
+#[doc(cfg(all()))]
+pub struct Simillimum;