about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--src/librustdoc/clean/types.rs40
-rw-r--r--tests/rustdoc/const-display.rs18
-rw-r--r--tests/rustdoc/stability.rs31
4 files changed, 82 insertions, 9 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index dcc4cf2478f..762ebc47ca9 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -153,7 +153,7 @@ pub enum StabilityLevel {
 }
 
 /// Rust release in which a feature is stabilized.
-#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
+#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
 #[derive(HashStable_Generic)]
 pub enum StableSince {
     Version(RustcVersion),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 31710bc014a..a0f44d152b2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -384,7 +384,45 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 
 impl Item {
     pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
-        self.def_id().and_then(|did| tcx.lookup_stability(did))
+        let (mut def_id, mut stability) = if let Some(inlined) = self.inline_stmt_id {
+            let inlined_def_id = inlined.to_def_id();
+            if let Some(stability) = tcx.lookup_stability(inlined_def_id) {
+                (inlined_def_id, stability)
+            } else {
+                // For re-exports into crates without `staged_api`, reuse the original stability.
+                // This is necessary, because we always want to mark unstable items.
+                let def_id = self.def_id()?;
+                return tcx.lookup_stability(def_id);
+            }
+        } else {
+            let def_id = self.def_id()?;
+            let stability = tcx.lookup_stability(def_id)?;
+            (def_id, stability)
+        };
+
+        let StabilityLevel::Stable { mut since, allowed_through_unstable_modules: false } =
+            stability.level
+        else {
+            return Some(stability);
+        };
+
+        // If any of the item's ancestors was stabilized later or is still unstable,
+        // then report the ancestor's stability instead.
+        while let Some(parent_def_id) = tcx.opt_parent(def_id) {
+            if let Some(parent_stability) = tcx.lookup_stability(parent_def_id) {
+                match parent_stability.level {
+                    StabilityLevel::Unstable { .. } => return Some(parent_stability),
+                    StabilityLevel::Stable { since: parent_since, .. } => {
+                        if parent_since > since {
+                            stability = parent_stability;
+                            since = parent_since;
+                        }
+                    }
+                }
+            }
+            def_id = parent_def_id;
+        }
+        Some(stability)
     }
 
     pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
diff --git a/tests/rustdoc/const-display.rs b/tests/rustdoc/const-display.rs
index ac55a6302f7..a71825d883d 100644
--- a/tests/rustdoc/const-display.rs
+++ b/tests/rustdoc/const-display.rs
@@ -1,8 +1,6 @@
 #![crate_name = "foo"]
 
-#![unstable(feature = "humans",
-            reason = "who ever let humans program computers, we're apparently really bad at it",
-            issue = "none")]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 #![feature(foo, foo2)]
 #![feature(staged_api)]
@@ -48,10 +46,18 @@ pub const unsafe fn foo2_gated() -> u32 { 42 }
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 pub const unsafe fn bar2_gated() -> u32 { 42 }
 
-//@ has 'foo/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32'
-//@ !hasraw - '//span[@class="since"]'
-pub const unsafe fn bar_not_gated() -> u32 { 42 }
+#[unstable(
+    feature = "humans",
+    reason = "who ever let humans program computers, we're apparently really bad at it",
+    issue = "none",
+)]
+pub mod unstable {
+    //@ has 'foo/unstable/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32'
+    //@ !hasraw - '//span[@class="since"]'
+    pub const unsafe fn bar_not_gated() -> u32 { 42 }
+}
 
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Foo;
 
 impl Foo {
diff --git a/tests/rustdoc/stability.rs b/tests/rustdoc/stability.rs
index 270da822c00..de855b43ba5 100644
--- a/tests/rustdoc/stability.rs
+++ b/tests/rustdoc/stability.rs
@@ -1,6 +1,6 @@
 #![feature(staged_api)]
 
-#![unstable(feature = "test", issue = "none")]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 //@ has stability/index.html
 //@ has - '//ul[@class="item-table"]/li[1]//a' AaStable
@@ -10,6 +10,7 @@
 #[stable(feature = "rust2", since = "2.2.2")]
 pub struct AaStable;
 
+#[unstable(feature = "test", issue = "none")]
 pub struct Unstable {
     //@ has stability/struct.Unstable.html \
     //      '//span[@class="item-info"]//div[@class="stab unstable"]' \
@@ -21,3 +22,31 @@ pub struct Unstable {
 
 #[stable(feature = "rust2", since = "2.2.2")]
 pub struct ZzStable;
+
+#[unstable(feature = "unstable", issue = "none")]
+pub mod unstable {
+    //@ !hasraw stability/unstable/struct.Foo.html '//span[@class="since"]'
+    //@ has - '//div[@class="stab unstable"]' 'experimental'
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct Foo;
+}
+
+#[stable(feature = "rust2", since = "2.2.2")]
+pub mod stable_later {
+    //@ has stability/stable_later/struct.Bar.html '//span[@class="since"]' '2.2.2'
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub struct Bar;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod stable_earlier {
+    //@ has stability/stable_earlier/struct.Foo.html '//span[@class="since"]' '1.0.0'
+    #[doc(inline)]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::unstable::Foo;
+
+    //@ has stability/stable_earlier/struct.Bar.html '//span[@class="since"]' '1.0.0'
+    #[doc(inline)]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::stable_later::Bar;
+}