Handle structured stable attribute 'since' version in rustdoc

This commit is contained in:
David Tolnay 2023-10-24 16:35:43 -07:00
parent 7b0e315ae6
commit 6933a671d3
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
6 changed files with 49 additions and 29 deletions

View File

@ -13,6 +13,7 @@ use rustc_session::parse::{feature_err, ParseSess};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::hygiene::Transparency; use rustc_span::hygiene::Transparency;
use rustc_span::{symbol::sym, symbol::Symbol, Span}; use rustc_span::{symbol::sym, symbol::Symbol, Span};
use std::fmt::{self, Display};
use std::num::NonZeroU32; use std::num::NonZeroU32;
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
@ -590,6 +591,12 @@ fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
Some(Version { major, minor, patch }) Some(Version { major, minor, patch })
} }
impl Display for Version {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
}
}
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
/// evaluate individual items. /// evaluate individual items.
pub fn eval_condition( pub fn eval_condition(

View File

@ -12,7 +12,7 @@ use thin_vec::ThinVec;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel}; use rustc_attr::{ConstStability, Deprecation, Since, Stability, StabilityLevel};
use rustc_const_eval::const_eval::is_unstable_const_fn; use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir; use rustc_hir as hir;
@ -585,14 +585,14 @@ impl Item {
}) })
} }
pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> { pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<Since> {
match self.stability(tcx)?.level { match self.stability(tcx)?.level {
StabilityLevel::Stable { since, .. } => Some(since), StabilityLevel::Stable { since, .. } => Some(since),
StabilityLevel::Unstable { .. } => None, StabilityLevel::Unstable { .. } => None,
} }
} }
pub(crate) fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> { pub(crate) fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<Since> {
match self.const_stability(tcx)?.level { match self.const_stability(tcx)?.level {
StabilityLevel::Stable { since, .. } => Some(since), StabilityLevel::Stable { since, .. } => Some(since),
StabilityLevel::Unstable { .. } => None, StabilityLevel::Unstable { .. } => None,

View File

@ -48,7 +48,7 @@ use std::str;
use std::string::ToString; use std::string::ToString;
use askama::Template; use askama::Template;
use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; use rustc_attr::{rust_version_symbol, ConstStability, Deprecation, Since, StabilityLevel};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::def_id::{DefId, DefIdSet};
@ -911,13 +911,17 @@ fn assoc_method(
/// consequence of the above rules. /// consequence of the above rules.
fn render_stability_since_raw_with_extra( fn render_stability_since_raw_with_extra(
w: &mut Buffer, w: &mut Buffer,
ver: Option<Symbol>, ver: Option<Since>,
const_stability: Option<ConstStability>, const_stability: Option<ConstStability>,
containing_ver: Option<Symbol>, containing_ver: Option<Since>,
containing_const_ver: Option<Symbol>, containing_const_ver: Option<Since>,
extra_class: &str, extra_class: &str,
) -> bool { ) -> bool {
let stable_version = ver.filter(|inner| !inner.is_empty() && Some(*inner) != containing_ver); let stable_version = if ver != containing_ver && let Some(ver) = &ver {
since_to_string(ver)
} else {
None
};
let mut title = String::new(); let mut title = String::new();
let mut stability = String::new(); let mut stability = String::new();
@ -931,7 +935,8 @@ fn render_stability_since_raw_with_extra(
Some(ConstStability { level: StabilityLevel::Stable { since, .. }, .. }) Some(ConstStability { level: StabilityLevel::Stable { since, .. }, .. })
if Some(since) != containing_const_ver => if Some(since) != containing_const_ver =>
{ {
Some((format!("const since {since}"), format!("const: {since}"))) since_to_string(&since)
.map(|since| (format!("const since {since}"), format!("const: {since}")))
} }
Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => { Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => {
let unstable = if let Some(n) = issue { let unstable = if let Some(n) = issue {
@ -971,13 +976,21 @@ fn render_stability_since_raw_with_extra(
!stability.is_empty() !stability.is_empty()
} }
fn since_to_string(since: &Since) -> Option<String> {
match since {
Since::Version(since) => Some(since.to_string()),
Since::Current => Some(rust_version_symbol().to_string()),
Since::Err => None,
}
}
#[inline] #[inline]
fn render_stability_since_raw( fn render_stability_since_raw(
w: &mut Buffer, w: &mut Buffer,
ver: Option<Symbol>, ver: Option<Since>,
const_stability: Option<ConstStability>, const_stability: Option<ConstStability>,
containing_ver: Option<Symbol>, containing_ver: Option<Since>,
containing_const_ver: Option<Symbol>, containing_const_ver: Option<Since>,
) -> bool { ) -> bool {
render_stability_since_raw_with_extra( render_stability_since_raw_with_extra(
w, w,

View File

@ -11,20 +11,20 @@
// @files 'src/foo' '[]' // @files 'src/foo' '[]'
// @has foo/fn.foo.html // @has foo/fn.foo.html
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · ' // @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' // @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
#[stable(feature = "bar", since = "1.0")] #[stable(feature = "bar", since = "1.0")]
pub fn foo() {} pub fn foo() {}
// @has foo/struct.Bar.html // @has foo/struct.Bar.html
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · ' // @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' // @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
#[stable(feature = "bar", since = "1.0")] #[stable(feature = "bar", since = "1.0")]
pub struct Bar; pub struct Bar;
impl Bar { impl Bar {
// @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0' // @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0.0'
// @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0 ·' // @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0.0 ·'
#[stable(feature = "foobar", since = "2.0")] #[stable(feature = "foobar", since = "2.0")]
pub fn bar() {} pub fn bar() {}
} }

View File

@ -3,23 +3,23 @@
#![feature(staged_api)] #![feature(staged_api)]
// @has foo/trait.Bar.html // @has foo/trait.Bar.html
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' // @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
#[stable(feature = "bar", since = "1.0")] #[stable(feature = "bar", since = "1.0")]
pub trait Bar { pub trait Bar {
// @has - '//*[@id="tymethod.foo"]/*[@class="rightside"]' '3.0 · source' // @has - '//*[@id="tymethod.foo"]/*[@class="rightside"]' '3.0.0 · source'
#[stable(feature = "foobar", since = "3.0")] #[stable(feature = "foobar", since = "3.0")]
fn foo(); fn foo();
} }
// @has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0 · source' // @has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0.0 · source'
// @has foo/struct.Foo.html // @has foo/struct.Foo.html
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' // @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
#[stable(feature = "baz", since = "1.0")] #[stable(feature = "baz", since = "1.0")]
pub struct Foo; pub struct Foo;
impl Foo { impl Foo {
// @has - '//*[@id="method.foofoo"]/*[@class="rightside"]' '3.0 · source' // @has - '//*[@id="method.foofoo"]/*[@class="rightside"]' '3.0.0 · source'
#[stable(feature = "foobar", since = "3.0")] #[stable(feature = "foobar", since = "3.0")]
pub fn foofoo() {} pub fn foofoo() {}
} }

View File

@ -4,20 +4,20 @@
#![crate_name = "foo"] #![crate_name = "foo"]
// @has foo/fn.foo.html // @has foo/fn.foo.html
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · ' // @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' // @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
#[stable(feature = "bar", since = "1.0")] #[stable(feature = "bar", since = "1.0")]
pub fn foo() {} pub fn foo() {}
// @has foo/struct.Bar.html // @has foo/struct.Bar.html
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · ' // @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · ' // @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
#[stable(feature = "bar", since = "1.0")] #[stable(feature = "bar", since = "1.0")]
pub struct Bar; pub struct Bar;
impl Bar { impl Bar {
// @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0' // @has - '//*[@id="method.bar"]/*[@class="since rightside"]' '2.0.0'
// @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0 ·' // @!has - '//*[@id="method.bar"]/*[@class="rightside"]' '2.0.0 ·'
#[stable(feature = "foobar", since = "2.0")] #[stable(feature = "foobar", since = "2.0")]
pub fn bar() {} pub fn bar() {}
} }