@@ -21,19 +21,17 @@ pub(crate) const PROPAGATE_STABILITY: Pass = Pass {
21
21
} ;
22
22
23
23
pub ( crate ) fn propagate_stability ( cr : Crate , cx : & mut DocContext < ' _ > ) -> Crate {
24
- let crate_stability = cx. tcx . lookup_stability ( CRATE_DEF_ID ) ;
24
+ let crate_stability = cx. tcx . lookup_stability ( CRATE_DEF_ID ) . cloned ( ) ;
25
25
StabilityPropagator { parent_stability : crate_stability, cx } . fold_crate ( cr)
26
26
}
27
27
28
28
struct StabilityPropagator < ' a , ' tcx > {
29
- parent_stability : Option < & ' tcx Stability > ,
29
+ parent_stability : Option < Stability > ,
30
30
cx : & ' a mut DocContext < ' tcx > ,
31
31
}
32
32
33
33
impl < ' a , ' tcx > DocFolder for StabilityPropagator < ' a , ' tcx > {
34
34
fn fold_item ( & mut self , mut item : Item ) -> Option < Item > {
35
- let parent_stability = self . parent_stability ;
36
-
37
35
let stability = match item. item_id {
38
36
ItemId :: DefId ( def_id) => {
39
37
let own_stability = self . cx . tcx . lookup_stability ( def_id) ;
@@ -59,9 +57,7 @@ impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> {
59
57
| ItemKind :: MacroItem ( ..)
60
58
| ItemKind :: ProcMacroItem ( ..)
61
59
| ItemKind :: ConstantItem ( ..) => {
62
- // If any of the item's parents was stabilized later or is still unstable,
63
- // then use the parent's stability instead.
64
- merge_stability ( own_stability, parent_stability)
60
+ merge_stability ( own_stability, self . parent_stability . as_ref ( ) )
65
61
}
66
62
67
63
// Don't inherit the parent's stability for these items, because they
@@ -74,7 +70,7 @@ impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> {
74
70
| ItemKind :: TyAssocTypeItem ( ..)
75
71
| ItemKind :: AssocTypeItem ( ..)
76
72
| ItemKind :: PrimitiveItem ( ..)
77
- | ItemKind :: KeywordItem => own_stability,
73
+ | ItemKind :: KeywordItem => own_stability. cloned ( ) ,
78
74
79
75
ItemKind :: StrippedItem ( ..) => unreachable ! ( ) ,
80
76
}
@@ -85,28 +81,53 @@ impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> {
85
81
}
86
82
} ;
87
83
88
- item. inner . stability = stability. cloned ( ) ;
89
- self . parent_stability = stability;
84
+ item. inner . stability = stability. clone ( ) ;
85
+ let parent_stability = std :: mem :: replace ( & mut self . parent_stability , stability) ;
90
86
let item = self . fold_item_recur ( item) ;
91
87
self . parent_stability = parent_stability;
92
88
93
89
Some ( item)
94
90
}
95
91
}
96
92
97
- fn merge_stability < ' tcx > (
98
- own_stability : Option < & ' tcx Stability > ,
99
- parent_stability : Option < & ' tcx Stability > ,
100
- ) -> Option < & ' tcx Stability > {
93
+ fn merge_stability (
94
+ own_stability : Option < & Stability > ,
95
+ parent_stability : Option < & Stability > ,
96
+ ) -> Option < Stability > {
101
97
if let Some ( own_stab) = own_stability
102
- && let & StabilityLevel :: Stable { since : own_since, allowed_through_unstable_modules : false } =
103
- & own_stab. level
104
98
&& let Some ( parent_stab) = parent_stability
105
- && ( parent_stab. is_unstable ( )
106
- || parent_stab. stable_since ( ) . is_some_and ( |parent_since| parent_since > own_since) )
107
99
{
108
- parent_stability
100
+ match own_stab. level {
101
+ // If any of a stable item's parents were stabilized later or are still unstable,
102
+ // then use the parent's stability instead.
103
+ StabilityLevel :: Stable {
104
+ since : own_since,
105
+ allowed_through_unstable_modules : false ,
106
+ ..
107
+ } if parent_stab. is_unstable ( )
108
+ || parent_stab
109
+ . stable_since ( )
110
+ . is_some_and ( |parent_since| parent_since > own_since) =>
111
+ {
112
+ parent_stability. cloned ( )
113
+ }
114
+
115
+ // If any of an unstable item's parents depend on other unstable features,
116
+ // then use those as well.
117
+ StabilityLevel :: Unstable { unstables : ref own_gates, reason, is_soft }
118
+ if let StabilityLevel :: Unstable { unstables : parent_gates, .. } =
119
+ & parent_stab. level =>
120
+ {
121
+ let missing_unstables = parent_gates
122
+ . iter ( )
123
+ . filter ( |p| !own_gates. iter ( ) . any ( |u| u. feature == p. feature ) ) ;
124
+ let unstables = own_gates. iter ( ) . chain ( missing_unstables) . cloned ( ) . collect ( ) ;
125
+ Some ( Stability { level : StabilityLevel :: Unstable { unstables, reason, is_soft } } )
126
+ }
127
+
128
+ _ => own_stability. cloned ( ) ,
129
+ }
109
130
} else {
110
- own_stability
131
+ own_stability. cloned ( )
111
132
}
112
133
}
0 commit comments