about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWim Looman <git@nemo157.com>2020-11-04 21:59:35 +0100
committerGuillaume Gomez <guillaume.gomez@huawei.com>2021-10-05 18:04:15 +0200
commit18fdd816b72cbf1547efbb81f164f7a457f17b78 (patch)
tree838520193f9832ddafa6ab4977b415edf5f0208a
parent10cdbd847fd00d093ce89a4fffde5d90c8bb9817 (diff)
downloadrust-18fdd816b72cbf1547efbb81f164f7a457f17b78.tar.gz
rust-18fdd816b72cbf1547efbb81f164f7a457f17b78.zip
Allow adding a set of cfg's to hide from being implicitly doc(cfg)'d
By adding #![doc(cfg_hide(foobar))] to the crate attributes the cfg
 #[cfg(foobar)] (and _only_ that _exact_ cfg) will not be implicitly
treated as a doc(cfg) to render a message in the documentation.
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs9
-rw-r--r--src/librustdoc/doctest.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs2
-rw-r--r--src/librustdoc/visit_ast.rs24
-rw-r--r--src/test/rustdoc/doc-cfg-hide.rs32
11 files changed, 74 insertions, 9 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 06e9d9ed329..bce5cd8174d 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -279,6 +279,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
                 gate_doc!(
                     cfg => doc_cfg
+                    cfg_hide => doc_cfg_hide
                     masked => doc_masked
                     notable_trait => doc_notable_trait
                     keyword => doc_keyword
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index eae7f7854ec..e5c57d0ee30 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -380,6 +380,9 @@ declare_features! (
     /// Allows `#[doc(cfg(...))]`.
     (active, doc_cfg, "1.21.0", Some(43781), None),
 
+    /// Allows `#[doc(cfg_hide(...))]`.
+    (active, doc_cfg_hide, "1.49.0", Some(43781), None),
+
     /// Allows `#[doc(masked)]`.
     (active, doc_masked, "1.21.0", Some(44027), None),
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 77baf7d7381..382dbc377d6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -399,6 +399,7 @@ symbols! {
         cfg_attr_multi,
         cfg_doctest,
         cfg_eval,
+        cfg_hide,
         cfg_panic,
         cfg_sanitize,
         cfg_target_abi,
@@ -547,6 +548,7 @@ symbols! {
         doc,
         doc_alias,
         doc_cfg,
+        doc_cfg_hide,
         doc_keyword,
         doc_masked,
         doc_notable_trait,
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 39493f6edf8..b463c1dc714 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.tcx),
+            both.cfg(cx.tcx, &cx.cache.hidden_cfg),
         )
     } else {
-        (old_attrs.clean(cx), old_attrs.cfg(cx.tcx))
+        (old_attrs.clean(cx), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 41bc30fd398..969d15dd6a1 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.tcx),
+        cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
     }]
 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 288644ff296..ebbf280d96d 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.tcx),
+            ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
         )
     }
 
@@ -747,7 +747,7 @@ crate trait AttributesExt {
 
     fn other_attrs(&self) -> Vec<ast::Attribute>;
 
-    fn cfg(&self, tcx: TyCtxt<'_>) -> Option<Arc<Cfg>>;
+    fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
 }
 
 impl AttributesExt for [ast::Attribute] {
@@ -772,7 +772,7 @@ impl AttributesExt for [ast::Attribute] {
         self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
     }
 
-    fn cfg(&self, tcx: TyCtxt<'_>) -> Option<Arc<Cfg>> {
+    fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
         let sess = tcx.sess;
         let doc_cfg_active = tcx.features().doc_cfg;
 
@@ -813,6 +813,7 @@ impl AttributesExt for [ast::Attribute] {
                     .filter_map(|attr| {
                         Cfg::parse(&attr).map_err(|e| sess.diagnostic().span_err(e.span, e.msg)).ok()
                     })
+                    .filter(|cfg| !hidden_cfg.contains(cfg))
                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
             }
         } else {
@@ -844,6 +845,8 @@ impl AttributesExt for [ast::Attribute] {
             }
         }
 
+        // treat #[target_feature(enable = "feat")] attributes as if they were
+        // #[doc(cfg(target_feature = "feat"))] attributes as well
         for attr in self.lists(sym::target_feature) {
             if attr.has_name(sym::enable) {
                 if let Some(feat) = attr.value_str() {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 8cf7b50fbd9..9e64d200b43 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.tcx) {
+        if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
             if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
                 return;
             }
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index bcfcc3d7039..cc9e081add1 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -119,6 +119,8 @@ crate struct Cache {
     ///
     /// Links are indexed by the DefId of the item they document.
     crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
+    /// Cfg that have been hidden via #![doc(cfg_hide(...))]
+    crate hidden_cfg: FxHashSet<clean::cfg::Cfg>,
 }
 
 /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index e68e1223171..e3ffc1e3f21 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.tcx()),
+                        cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
                         ..myitem.clone()
                     };
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 4f5495a176d..cd657fa01d4 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -3,6 +3,7 @@
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
+use rustc_hir::CRATE_HIR_ID;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
@@ -15,7 +16,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
 
 use std::mem;
 
-use crate::clean::{self, AttributesExt, NestedAttributesExt};
+use crate::clean::{self, cfg::Cfg, AttributesExt, NestedAttributesExt};
 use crate::core;
 use crate::doctree::*;
 
@@ -97,6 +98,27 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 }
             }
         }
+
+        self.cx.cache.hidden_cfg = self.cx.tcx.hir().attrs(CRATE_HIR_ID)
+            .iter()
+            .filter(|attr| attr.has_name(sym::doc))
+            .flat_map(|attr| attr.meta_item_list().into_iter().flatten())
+            .filter(|attr| attr.has_name(sym::cfg_hide))
+            .flat_map(|attr| {
+                attr.meta_item_list()
+                    .unwrap_or(&[])
+                    .iter()
+                    .filter_map(|attr| {
+                        Some(
+                            Cfg::parse(attr.meta_item()?)
+                                .map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg))
+                                .ok()?,
+                        )
+                    })
+                    .collect::<Vec<_>>()
+            })
+            .collect();
+
         self.cx.cache.exact_paths = self.exact_paths;
         top_level_module
     }
diff --git a/src/test/rustdoc/doc-cfg-hide.rs b/src/test/rustdoc/doc-cfg-hide.rs
new file mode 100644
index 00000000000..b9d0d323137
--- /dev/null
+++ b/src/test/rustdoc/doc-cfg-hide.rs
@@ -0,0 +1,32 @@
+#![crate_name = "oud"]
+#![feature(doc_cfg, doc_cfg_hide)]
+
+#![doc(cfg_hide(feature = "solecism"))]
+
+// @has 'oud/struct.Solecism.html'
+// @count   - '//*[@class="stab portability"]' 0
+// compile-flags:--cfg feature="solecism"
+#[cfg(feature = "solecism")]
+pub struct Solecism;
+
+// @has 'oud/struct.Scribacious.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature solecism'
+#[cfg(feature = "solecism")]
+#[doc(cfg(feature = "solecism"))]
+pub struct Scribacious;
+
+// @has 'oud/struct.Hyperdulia.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate feature hyperdulia'
+// compile-flags:--cfg feature="hyperdulia"
+#[cfg(feature = "solecism")]
+#[cfg(feature = "hyperdulia")]
+pub struct Hyperdulia;
+
+// @has 'oud/struct.Oystercatcher.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' 'crate features solecism and oystercatcher'
+// compile-flags:--cfg feature="oystercatcher"
+#[cfg(all(feature = "solecism", feature = "oystercatcher"))]
+pub struct Oystercatcher;