Skip to content

Commit d670842

Browse files
authored
Rollup merge of rust-lang#48759 - QuietMisdreavus:simd-feature-docs, r=GuillaumeGomez
rustdoc: expose #[target_feature] attributes as doc(cfg) flags This change exposes `#[target_feature(enable = "feat")]` attributes on an item as if they were also `#[doc(cfg(target_feature = "feat"))]` attributes. This gives them a banner on their documentation listing which feature is required to use the item. It also modifies the rendering code for doc(cfg) tags to handle `target_feature` tags. I made it print just the feature name on "short" printings (as in the function listing on a module page), and use "target feature `feat`" in the full banner on the item page itself. This way, the function listing in `std::arch` shows which feature is required for each function: ![image](https://user-images.githubusercontent.com/5217170/37003222-f41b9d66-2091-11e8-9656-8719e5b34832.png) ![image](https://user-images.githubusercontent.com/5217170/37003234-feb1a7a2-2091-11e8-94de-6d1d76a2d3ee.png)
2 parents a848336 + b3fb0d1 commit d670842

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

src/librustdoc/clean/cfg.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl Cfg {
138138

139139
/// Renders the configuration for human display, as a short HTML description.
140140
pub(crate) fn render_short_html(&self) -> String {
141-
let mut msg = Html(self).to_string();
141+
let mut msg = ShortHtml(self).to_string();
142142
if self.should_capitalize_first_letter() {
143143
if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
144144
msg[i .. i+1].make_ascii_uppercase();
@@ -149,7 +149,13 @@ impl Cfg {
149149

150150
/// Renders the configuration for long display, as a long HTML description.
151151
pub(crate) fn render_long_html(&self) -> String {
152-
let mut msg = format!("This is supported on <strong>{}</strong>", Html(self));
152+
let on = if self.should_use_with_in_description() {
153+
"with"
154+
} else {
155+
"on"
156+
};
157+
158+
let mut msg = format!("This is supported {} <strong>{}</strong>", on, Html(self));
153159
if self.should_append_only_to_description() {
154160
msg.push_str(" only");
155161
}
@@ -180,6 +186,13 @@ impl Cfg {
180186
}
181187
}
182188
}
189+
190+
fn should_use_with_in_description(&self) -> bool {
191+
match *self {
192+
Cfg::Cfg(ref name, _) if name == &"target_feature" => true,
193+
_ => false,
194+
}
195+
}
183196
}
184197

185198
impl ops::Not for Cfg {
@@ -376,6 +389,8 @@ impl<'a> fmt::Display for Html<'a> {
376389
},
377390
("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
378391
("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
392+
("target_feature", Some(feat)) =>
393+
return write!(fmt, "target feature <code>{}</code>", feat),
379394
_ => "",
380395
};
381396
if !human_readable.is_empty() {
@@ -390,6 +405,19 @@ impl<'a> fmt::Display for Html<'a> {
390405
}
391406
}
392407

408+
struct ShortHtml<'a>(&'a Cfg);
409+
410+
impl<'a> fmt::Display for ShortHtml<'a> {
411+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
412+
match *self.0 {
413+
Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => {
414+
write!(fmt, "<code>{}</code>", vendor)
415+
},
416+
ref cfg => write!(fmt, "{}", Html(cfg)),
417+
}
418+
}
419+
}
420+
393421
#[cfg(test)]
394422
mod test {
395423
use super::Cfg;
@@ -824,6 +852,10 @@ mod test {
824852
).render_short_html(),
825853
"(Debug-assertions enabled or Windows) and Unix"
826854
);
855+
assert_eq!(
856+
name_value_cfg("target_feature", "sse2").render_short_html(),
857+
"<code>sse2</code>"
858+
);
827859
})
828860
}
829861

@@ -898,6 +930,10 @@ mod test {
898930
"This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
899931
</strong> only."
900932
);
933+
assert_eq!(
934+
name_value_cfg("target_feature", "sse2").render_long_html(),
935+
"This is supported with <strong>target feature <code>sse2</code></strong> only."
936+
);
901937
})
902938
}
903939
}

src/librustdoc/clean/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,19 @@ impl Attributes {
828828
})
829829
}).collect();
830830

831+
// treat #[target_feature(enable = "feat")] attributes as if they were
832+
// #[doc(cfg(target_feature = "feat"))] attributes as well
833+
for attr in attrs.lists("target_feature") {
834+
if attr.check_name("enable") {
835+
if let Some(feat) = attr.value_str() {
836+
let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
837+
if let Ok(feat_cfg) = Cfg::parse(&meta) {
838+
cfg &= feat_cfg;
839+
}
840+
}
841+
}
842+
}
843+
831844
Attributes {
832845
doc_strings,
833846
other_attrs,

src/test/rustdoc/doc-cfg.rs

+24
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![feature(doc_cfg)]
12+
#![feature(target_feature, cfg_target_feature)]
1213

1314
// @has doc_cfg/struct.Portable.html
1415
// @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
@@ -45,3 +46,26 @@ pub mod unix_only {
4546
fn unix_and_arm_only_function() {}
4647
}
4748
}
49+
50+
// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
51+
// item as well
52+
53+
// the portability header is different on the module view versus the full view
54+
// @has doc_cfg/index.html
55+
// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z'
56+
57+
// @has doc_cfg/fn.uses_target_feature.html
58+
// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
59+
// 'This is supported with target feature avx only.'
60+
#[target_feature(enable = "avx")]
61+
pub unsafe fn uses_target_feature() {
62+
content::should::be::irrelevant();
63+
}
64+
65+
// @has doc_cfg/fn.uses_cfg_target_feature.html
66+
// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
67+
// 'This is supported with target feature avx only.'
68+
#[doc(cfg(target_feature = "avx"))]
69+
pub fn uses_cfg_target_feature() {
70+
uses_target_feature();
71+
}

0 commit comments

Comments
 (0)