Skip to content

Commit 85ec783

Browse files
Nemo157jyn514
authored andcommitted
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)
1 parent 7bd62a8 commit 85ec783

File tree

8 files changed

+109
-54
lines changed

8 files changed

+109
-54
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ fn merge_attrs(
296296
if let Some(inner) = new_attrs {
297297
if let Some(new_id) = parent_module {
298298
let diag = cx.sess().diagnostic();
299-
Attributes::from_ast(diag, old_attrs, Some((inner, new_id)))
299+
let doc_cfg_active = cx.tcx.features().doc_cfg;
300+
Attributes::from_ast(diag, old_attrs, Some((inner, new_id)), doc_cfg_active)
300301
} else {
301302
let mut both = inner.to_vec();
302303
both.extend_from_slice(old_attrs);

src/librustdoc/clean/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ impl Clean<Item> for doctree::Module<'_> {
124124

125125
impl Clean<Attributes> for [ast::Attribute] {
126126
fn clean(&self, cx: &mut DocContext<'_>) -> Attributes {
127-
Attributes::from_ast(cx.sess().diagnostic(), self, None)
127+
let doc_cfg_active = cx.tcx.features().doc_cfg;
128+
Attributes::from_ast(cx.sess().diagnostic(), self, None, doc_cfg_active)
128129
}
129130
}
130131

src/librustdoc/clean/types.rs

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -811,29 +811,6 @@ pub struct RenderedLink {
811811
}
812812

813813
impl Attributes {
814-
/// Extracts the content from an attribute `#[doc(cfg(content))]`.
815-
crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
816-
use rustc_ast::NestedMetaItem::MetaItem;
817-
818-
if let ast::MetaItemKind::List(ref nmis) = mi.kind {
819-
if nmis.len() == 1 {
820-
if let MetaItem(ref cfg_mi) = nmis[0] {
821-
if cfg_mi.has_name(sym::cfg) {
822-
if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
823-
if cfg_nmis.len() == 1 {
824-
if let MetaItem(ref content_mi) = cfg_nmis[0] {
825-
return Some(content_mi);
826-
}
827-
}
828-
}
829-
}
830-
}
831-
}
832-
}
833-
834-
None
835-
}
836-
837814
/// Reads a `MetaItem` from within an attribute, looks for whether it is a
838815
/// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
839816
/// its expansion.
@@ -893,10 +870,10 @@ impl Attributes {
893870
diagnostic: &::rustc_errors::Handler,
894871
attrs: &[ast::Attribute],
895872
additional_attrs: Option<(&[ast::Attribute], DefId)>,
873+
doc_cfg_active: bool,
896874
) -> Attributes {
897875
let mut doc_strings: Vec<DocFragment> = vec![];
898876
let mut sp = None;
899-
let mut cfg = Cfg::True;
900877
let mut doc_line = 0;
901878

902879
fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
@@ -943,36 +920,27 @@ impl Attributes {
943920
if sp.is_none() {
944921
sp = Some(attr.span);
945922
}
946-
None
947-
} else {
948-
if attr.has_name(sym::doc) {
949-
if let Some(mi) = attr.meta() {
950-
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
951-
// Extracted #[doc(cfg(...))]
952-
match Cfg::parse(cfg_mi) {
953-
Ok(new_cfg) => cfg &= new_cfg,
954-
Err(e) => diagnostic.span_err(e.span, e.msg),
955-
}
956-
} else if let Some((filename, contents)) = Attributes::extract_include(&mi)
957-
{
958-
let line = doc_line;
959-
doc_line += contents.as_str().lines().count();
960-
let frag = DocFragment {
961-
line,
962-
span: attr.span,
963-
doc: contents,
964-
kind: DocFragmentKind::Include { filename },
965-
parent_module,
966-
need_backline: false,
967-
indent: 0,
968-
};
969-
update_need_backline(&mut doc_strings, &frag);
970-
doc_strings.push(frag);
971-
}
923+
return None;
924+
} else if attr.has_name(sym::doc) {
925+
if let Some(mi) = attr.meta() {
926+
if let Some((filename, contents)) = Attributes::extract_include(&mi) {
927+
let line = doc_line;
928+
doc_line += contents.as_str().lines().count();
929+
let frag = DocFragment {
930+
line,
931+
span: attr.span,
932+
doc: contents,
933+
kind: DocFragmentKind::Include { filename },
934+
parent_module,
935+
need_backline: false,
936+
indent: 0,
937+
};
938+
update_need_backline(&mut doc_strings, &frag);
939+
doc_strings.push(frag);
972940
}
973941
}
974-
Some(attr.clone())
975942
}
943+
Some(attr.clone())
976944
};
977945

978946
// Additional documentation should be shown before the original documentation
@@ -984,6 +952,49 @@ impl Attributes {
984952
.filter_map(clean_attr)
985953
.collect();
986954

955+
trait SingleExt {
956+
type Item;
957+
fn single(self) -> Option<Self::Item>;
958+
}
959+
960+
impl<T: IntoIterator> SingleExt for T {
961+
type Item = T::Item;
962+
fn single(self) -> Option<Self::Item> {
963+
let mut iter = self.into_iter();
964+
let item = iter.next()?;
965+
iter.next().is_none().then_some(())?;
966+
Some(item)
967+
}
968+
}
969+
970+
let mut cfg = if doc_cfg_active {
971+
let mut doc_cfg = attrs
972+
.iter()
973+
.filter(|attr| attr.has_name(sym::doc))
974+
.filter_map(|attr| Some(attr.meta_item_list()?.single()?))
975+
.filter(|attr| attr.has_name(sym::cfg))
976+
.filter_map(|attr| Some(attr.meta_item_list()?.single()?.meta_item()?.clone()))
977+
.peekable();
978+
if doc_cfg.peek().is_some() {
979+
doc_cfg
980+
.filter_map(|attr| {
981+
Cfg::parse(&attr).map_err(|e| diagnostic.span_err(e.span, e.msg)).ok()
982+
})
983+
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
984+
} else {
985+
attrs
986+
.iter()
987+
.filter(|attr| attr.has_name(sym::cfg))
988+
.filter_map(|attr| Some(attr.meta_item_list()?.single()?.meta_item()?.clone()))
989+
.filter_map(|attr| {
990+
Cfg::parse(&attr).map_err(|e| diagnostic.span_err(e.span, e.msg)).ok()
991+
})
992+
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
993+
}
994+
} else {
995+
Cfg::True
996+
};
997+
987998
// treat #[target_feature(enable = "feat")] attributes as if they were
988999
// #[doc(cfg(target_feature = "feat"))] attributes as well
9891000
for attr in attrs.lists(sym::target_feature) {

src/librustdoc/doctest.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,8 +1092,9 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
10921092
sp: Span,
10931093
nested: F,
10941094
) {
1095+
let doc_cfg_active = self.tcx.features().doc_cfg;
10951096
let attrs = self.tcx.hir().attrs(hir_id);
1096-
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None);
1097+
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None, doc_cfg_active);
10971098
if let Some(ref cfg) = attrs.cfg {
10981099
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
10991100
return;

src/librustdoc/html/render/print_item.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,12 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
284284

285285
clean::ImportItem(ref import) => {
286286
let (stab, stab_tags) = if let Some(import_def_id) = import.source.did {
287+
let doc_cfg_active = cx.tcx().features().doc_cfg;
287288
let import_attrs = Box::new(clean::Attributes::from_ast(
288289
cx.tcx().sess().diagnostic(),
289290
cx.tcx().get_attrs(import_def_id),
290291
None,
292+
doc_cfg_active,
291293
));
292294

293295
// Just need an item with the correct def_id and attrs

src/librustdoc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
)]
55
#![feature(rustc_private)]
66
#![feature(array_methods)]
7+
#![feature(bool_to_option)]
78
#![feature(box_patterns)]
89
#![feature(box_syntax)]
910
#![feature(in_band_lifetimes)]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compile-flags:--cfg feature="worricow"
2+
#![crate_name = "xenogenous"]
3+
4+
// @has 'xenogenous/struct.Worricow.html'
5+
// @count - '//*[@class="stab portability"]' 0
6+
#[cfg(feature = "worricow")]
7+
pub struct Worricow;

src/test/rustdoc/doc-cfg-implicit.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![crate_name = "funambulism"]
2+
#![feature(doc_cfg)]
3+
4+
// @has 'funambulism/struct.Disorbed.html'
5+
// @count - '//*[@class="stab portability"]' 1
6+
// @matches - '//*[@class="stab portability"]' 'crate feature disorbed'
7+
// compile-flags:--cfg feature="disorbed"
8+
#[cfg(feature = "disorbed")]
9+
pub struct Disorbed;
10+
11+
// @has 'funambulism/struct.Aesthesia.html'
12+
// @count - '//*[@class="stab portability"]' 1
13+
// @matches - '//*[@class="stab portability"]' 'crate feature aesthesia'
14+
// compile-flags:--cfg feature="aesthesia"
15+
#[doc(cfg(feature = "aesthesia"))]
16+
pub struct Aesthesia;
17+
18+
// @has 'funambulism/struct.Pliothermic.html'
19+
// @count - '//*[@class="stab portability"]' 1
20+
// @matches - '//*[@class="stab portability"]' 'crate feature pliothermic'
21+
// compile-flags:--cfg feature="epopoeist"
22+
#[cfg(feature = "epopoeist")]
23+
#[doc(cfg(feature = "pliothermic"))]
24+
pub struct Pliothermic;
25+
26+
// @has 'funambulism/struct.Simillimum.html'
27+
// @count - '//*[@class="stab portability"]' 0
28+
// compile-flags:--cfg feature="simillimum"
29+
#[cfg(feature = "simillimum")]
30+
#[doc(cfg(all()))]
31+
pub struct Simillimum;

0 commit comments

Comments
 (0)