Rollup merge of #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)
This commit is contained in:
commit
d67084215d
@ -138,7 +138,7 @@ impl Cfg {
|
|||||||
|
|
||||||
/// Renders the configuration for human display, as a short HTML description.
|
/// Renders the configuration for human display, as a short HTML description.
|
||||||
pub(crate) fn render_short_html(&self) -> String {
|
pub(crate) fn render_short_html(&self) -> String {
|
||||||
let mut msg = Html(self).to_string();
|
let mut msg = ShortHtml(self).to_string();
|
||||||
if self.should_capitalize_first_letter() {
|
if self.should_capitalize_first_letter() {
|
||||||
if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
|
if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
|
||||||
msg[i .. i+1].make_ascii_uppercase();
|
msg[i .. i+1].make_ascii_uppercase();
|
||||||
@ -149,7 +149,13 @@ impl Cfg {
|
|||||||
|
|
||||||
/// Renders the configuration for long display, as a long HTML description.
|
/// Renders the configuration for long display, as a long HTML description.
|
||||||
pub(crate) fn render_long_html(&self) -> String {
|
pub(crate) fn render_long_html(&self) -> String {
|
||||||
let mut msg = format!("This is supported on <strong>{}</strong>", Html(self));
|
let on = if self.should_use_with_in_description() {
|
||||||
|
"with"
|
||||||
|
} else {
|
||||||
|
"on"
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut msg = format!("This is supported {} <strong>{}</strong>", on, Html(self));
|
||||||
if self.should_append_only_to_description() {
|
if self.should_append_only_to_description() {
|
||||||
msg.push_str(" only");
|
msg.push_str(" only");
|
||||||
}
|
}
|
||||||
@ -180,6 +186,13 @@ impl Cfg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_use_with_in_description(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Cfg::Cfg(ref name, _) if name == &"target_feature" => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Not for Cfg {
|
impl ops::Not for Cfg {
|
||||||
@ -376,6 +389,8 @@ impl<'a> fmt::Display for Html<'a> {
|
|||||||
},
|
},
|
||||||
("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
|
("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
|
||||||
("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
|
("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
|
||||||
|
("target_feature", Some(feat)) =>
|
||||||
|
return write!(fmt, "target feature <code>{}</code>", feat),
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
if !human_readable.is_empty() {
|
if !human_readable.is_empty() {
|
||||||
@ -390,6 +405,19 @@ impl<'a> fmt::Display for Html<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ShortHtml<'a>(&'a Cfg);
|
||||||
|
|
||||||
|
impl<'a> fmt::Display for ShortHtml<'a> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self.0 {
|
||||||
|
Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => {
|
||||||
|
write!(fmt, "<code>{}</code>", vendor)
|
||||||
|
},
|
||||||
|
ref cfg => write!(fmt, "{}", Html(cfg)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Cfg;
|
use super::Cfg;
|
||||||
@ -824,6 +852,10 @@ mod test {
|
|||||||
).render_short_html(),
|
).render_short_html(),
|
||||||
"(Debug-assertions enabled or Windows) and Unix"
|
"(Debug-assertions enabled or Windows) and Unix"
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
name_value_cfg("target_feature", "sse2").render_short_html(),
|
||||||
|
"<code>sse2</code>"
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -898,6 +930,10 @@ mod test {
|
|||||||
"This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
|
"This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
|
||||||
</strong> only."
|
</strong> only."
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
name_value_cfg("target_feature", "sse2").render_long_html(),
|
||||||
|
"This is supported with <strong>target feature <code>sse2</code></strong> only."
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -828,6 +828,19 @@ impl Attributes {
|
|||||||
})
|
})
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
// treat #[target_feature(enable = "feat")] attributes as if they were
|
||||||
|
// #[doc(cfg(target_feature = "feat"))] attributes as well
|
||||||
|
for attr in attrs.lists("target_feature") {
|
||||||
|
if attr.check_name("enable") {
|
||||||
|
if let Some(feat) = attr.value_str() {
|
||||||
|
let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
|
||||||
|
if let Ok(feat_cfg) = Cfg::parse(&meta) {
|
||||||
|
cfg &= feat_cfg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Attributes {
|
Attributes {
|
||||||
doc_strings,
|
doc_strings,
|
||||||
other_attrs,
|
other_attrs,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(doc_cfg)]
|
#![feature(doc_cfg)]
|
||||||
|
#![feature(target_feature, cfg_target_feature)]
|
||||||
|
|
||||||
// @has doc_cfg/struct.Portable.html
|
// @has doc_cfg/struct.Portable.html
|
||||||
// @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
|
// @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
|
||||||
@ -45,3 +46,26 @@ pub mod unix_only {
|
|||||||
fn unix_and_arm_only_function() {}
|
fn unix_and_arm_only_function() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
|
||||||
|
// item as well
|
||||||
|
|
||||||
|
// the portability header is different on the module view versus the full view
|
||||||
|
// @has doc_cfg/index.html
|
||||||
|
// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z'
|
||||||
|
|
||||||
|
// @has doc_cfg/fn.uses_target_feature.html
|
||||||
|
// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
||||||
|
// 'This is supported with target feature avx only.'
|
||||||
|
#[target_feature(enable = "avx")]
|
||||||
|
pub unsafe fn uses_target_feature() {
|
||||||
|
content::should::be::irrelevant();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has doc_cfg/fn.uses_cfg_target_feature.html
|
||||||
|
// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
||||||
|
// 'This is supported with target feature avx only.'
|
||||||
|
#[doc(cfg(target_feature = "avx"))]
|
||||||
|
pub fn uses_cfg_target_feature() {
|
||||||
|
uses_target_feature();
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user