diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index dda7490493197..3dfe03b54e9f2 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -792,6 +792,20 @@ fn assoc_type(
}
}
+/// Writes a span containing the versions at which an item became stable and/or const-stable. For
+/// example, if the item became stable at 1.0.0, and const-stable at 1.45.0, this function would
+/// write a span containing "1.0.0 (const: 1.45.0)".
+///
+/// Returns `true` if a stability annotation was rendered.
+///
+/// Stability and const-stability are considered separately. If the item is unstable, no version
+/// will be written. If the item is const-unstable, "const: unstable" will be appended to the
+/// span, with a link to the tracking issue if present. If an item's stability or const-stability
+/// version matches the version of its enclosing item, that version will be omitted.
+///
+/// Note that it is possible for an unstable function to be const-stable. In that case, the span
+/// will include the const-stable version, but no stable version will be emitted, as a natural
+/// consequence of the above rules.
fn render_stability_since_raw(
w: &mut Buffer,
ver: Option,
@@ -799,51 +813,56 @@ fn render_stability_since_raw(
containing_ver: Option,
containing_const_ver: Option,
) -> bool {
- let ver = ver.filter(|inner| !inner.is_empty());
+ let stable_version = ver.filter(|inner| !inner.is_empty() && Some(*inner) != containing_ver);
- match (ver, const_stability) {
- // stable and const stable
- (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. }))
+ let mut title = String::new();
+ let mut stability = String::new();
+
+ if let Some(ver) = stable_version {
+ stability.push_str(&ver.as_str());
+ title.push_str(&format!("Stable since Rust version {}", ver));
+ }
+
+ let const_title_and_stability = match const_stability {
+ Some(ConstStability { level: StabilityLevel::Stable { since }, .. })
if Some(since) != containing_const_ver =>
{
- write!(
- w,
- "{0} (const: {1})",
- v, since
- );
+ Some((format!("const since {}", since), format!("const: {}", since)))
}
- // stable and const unstable
- (
- Some(v),
- Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }),
- ) => {
- write!(
- w,
- "{0} (const: ",
- v
- );
- if let Some(n) = issue {
- write!(
- w,
- "unstable",
+ Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => {
+ let unstable = if let Some(n) = issue {
+ format!(
+ r#"unstable"#,
n, feature
- );
+ )
} else {
- write!(w, "unstable");
- }
- write!(w, ")");
+ String::from("unstable")
+ };
+
+ Some((String::from("const unstable"), format!("const: {}", unstable)))
}
- // stable
- (Some(v), _) if ver != containing_ver => {
- write!(
- w,
- "{0}",
- v
- );
+ _ => None,
+ };
+
+ if let Some((const_title, const_stability)) = const_title_and_stability {
+ if !title.is_empty() {
+ title.push_str(&format!(", {}", const_title));
+ } else {
+ title.push_str(&const_title);
+ }
+
+ if !stability.is_empty() {
+ stability.push_str(&format!(" ({})", const_stability));
+ } else {
+ stability.push_str(&const_stability);
}
- _ => return false,
}
- true
+
+ if !stability.is_empty() {
+ write!(w, r#"{}"#, title, stability);
+ }
+
+ !stability.is_empty()
}
fn render_assoc_item(
diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs
index fb8ea7e33c28c..b8e101038f8f1 100644
--- a/src/test/rustdoc/const-display.rs
+++ b/src/test/rustdoc/const-display.rs
@@ -67,3 +67,20 @@ impl Foo {
#[rustc_const_stable(feature = "rust1", since = "1.2.0")]
pub const fn stable_impl() -> u32 { 42 }
}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Bar;
+
+impl Bar {
+ // Do not show non-const stabilities that are the same as the enclosing item.
+ // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.2.0$'
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "rust1", since = "1.2.0")]
+ pub const fn stable_impl() -> u32 { 42 }
+
+ // Show const-stability even for unstable functions.
+ // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$'
+ #[unstable(feature = "foo2", issue = "none")]
+ #[rustc_const_stable(feature = "rust1", since = "1.3.0")]
+ pub const fn const_stable_unstable() -> u32 { 42 }
+}
diff --git a/src/test/rustdoc/deref-const-fn.rs b/src/test/rustdoc/deref-const-fn.rs
index ca51f3c7b5af0..8ecca6d12d24a 100644
--- a/src/test/rustdoc/deref-const-fn.rs
+++ b/src/test/rustdoc/deref-const-fn.rs
@@ -13,7 +13,7 @@ pub struct Bar;
impl Bar {
// @has - '//*[@id="method.len"]' 'pub const fn len(&self) -> usize'
- // @has - '//*[@id="method.len"]//span[@class="since"]' '1.0.0 (const: 1.0.0)'
+ // @has - '//*[@id="method.len"]//span[@class="since"]' 'const: 1.0.0'
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
pub const fn len(&self) -> usize { 0 }