@@ -162,19 +162,32 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
162
162
}
163
163
164
164
let stab = attr:: find_stability ( self . tcx . sess , attrs, item_sp) ;
165
- let const_stab = attr:: find_const_stability ( self . tcx . sess , attrs, item_sp) ;
165
+ let const_stab = attr:: find_const_stability (
166
+ self . tcx . sess ,
167
+ attrs,
168
+ item_sp,
169
+ // Compute the feature gate we inherit if this
170
+ // doesn't have its own feature gate.
171
+ self . parent_const_stab . and_then ( |c| c. feature ) . or_else ( || {
172
+ // Infer the const feature gate from the regular feature gate,
173
+ // but only if that regular gate is unstable.
174
+ if let Some ( ( s, _) ) = stab {
175
+ s. is_unstable ( ) . then_some ( s. feature )
176
+ } else if inherit_deprecation. yes ( )
177
+ && let Some ( parent_stab) = self . parent_stab
178
+ && parent_stab. is_unstable ( )
179
+ {
180
+ Some ( parent_stab. feature )
181
+ } else {
182
+ None
183
+ }
184
+ } ) ,
185
+ ) ;
166
186
let body_stab = attr:: find_body_stability ( self . tcx . sess , attrs) ;
167
- let mut const_span = None ;
168
-
169
- let const_stab = const_stab. map ( |( const_stab, const_span_node) | {
170
- self . index . const_stab_map . insert ( def_id, const_stab) ;
171
- const_span = Some ( const_span_node) ;
172
- const_stab
173
- } ) ;
174
187
175
188
// If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
176
189
// check if the function/method is const or the parent impl block is const
177
- if let ( Some ( const_span) , Some ( fn_sig) ) = ( const_span , fn_sig)
190
+ if let ( Some ( ( _ , const_span) ) , Some ( fn_sig) ) = ( const_stab , fn_sig)
178
191
&& fn_sig. header . abi != Abi :: RustIntrinsic
179
192
&& !fn_sig. header . is_const ( )
180
193
&& ( !self . in_trait_impl || !self . tcx . is_const_fn_raw ( def_id. to_def_id ( ) ) )
@@ -184,6 +197,22 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
184
197
. emit_err ( errors:: MissingConstErr { fn_sig_span : fn_sig. span , const_span } ) ;
185
198
}
186
199
200
+ // If this is marked const *stable*, it must also be regular-stable.
201
+ if let Some ( ( const_stab, const_span) ) = const_stab
202
+ && let Some ( fn_sig) = fn_sig
203
+ && const_stab. is_const_stable ( )
204
+ && !stab. is_some_and ( |( s, _) | s. is_stable ( ) )
205
+ {
206
+ self . tcx
207
+ . dcx ( )
208
+ . emit_err ( errors:: ConstStableNotStable { fn_sig_span : fn_sig. span , const_span } ) ;
209
+ }
210
+
211
+ let const_stab = const_stab. map ( |( const_stab, _span) | {
212
+ self . index . const_stab_map . insert ( def_id, const_stab) ;
213
+ const_stab
214
+ } ) ;
215
+
187
216
// `impl const Trait for Type` items forward their const stability to their
188
217
// immediate children.
189
218
if const_stab. is_none ( ) {
@@ -274,8 +303,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
274
303
}
275
304
}
276
305
277
- // Every `const fn` that has stability should also have const-stability.
278
-
279
306
self . recurse_with_stability_attrs (
280
307
depr. map ( |( d, _) | DeprecationEntry :: local ( d, def_id) ) ,
281
308
stab,
@@ -724,7 +751,15 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
724
751
if features. staged_api {
725
752
let attrs = self . tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
726
753
let stab = attr:: find_stability ( self . tcx . sess , attrs, item. span ) ;
727
- let const_stab = attr:: find_const_stability ( self . tcx . sess , attrs, item. span ) ;
754
+ // FIXME: this will give a different result than the normal stability
755
+ // computation, since we don't inherit stability from the parent. But that's
756
+ // true even for `stab` above so it's probably okay?
757
+ let const_stab = attr:: find_const_stability (
758
+ self . tcx . sess ,
759
+ attrs,
760
+ item. span ,
761
+ stab. map ( |( s, _) | s. feature ) ,
762
+ ) ;
728
763
729
764
// If this impl block has an #[unstable] attribute, give an
730
765
// error if all involved types and traits are stable, because
0 commit comments