@@ -16,7 +16,7 @@ use rustc_hir::def::{DefKind, Res};
16
16
use rustc_hir:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE , LocalDefId , LocalModDefId } ;
17
17
use rustc_hir:: hir_id:: CRATE_HIR_ID ;
18
18
use rustc_hir:: intravisit:: { self , Visitor } ;
19
- use rustc_hir:: { Constness , FieldDef , Item , ItemKind , TraitRef , Ty , TyKind , Variant } ;
19
+ use rustc_hir:: { FieldDef , Item , ItemKind , TraitRef , Ty , TyKind , Variant } ;
20
20
use rustc_middle:: hir:: nested_filter;
21
21
use rustc_middle:: middle:: lib_features:: { FeatureStability , LibFeatures } ;
22
22
use rustc_middle:: middle:: privacy:: EffectiveVisibilities ;
@@ -166,68 +166,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
166
166
return ;
167
167
}
168
168
169
+ // # Regular and body stability
170
+
169
171
let stab = attr:: find_stability ( self . tcx . sess , attrs, item_sp) ;
170
- let const_stab = attr:: find_const_stability (
171
- self . tcx . sess ,
172
- attrs,
173
- item_sp,
174
- fn_sig. is_some_and ( |s| s. header . is_const ( ) ) ,
175
- ) ;
176
172
let body_stab = attr:: find_body_stability ( self . tcx . sess , attrs) ;
177
173
178
- // If the current node is a function with const stability attributes (directly given or
179
- // implied), check if the function/method is const or the parent impl block is const.
180
- if let Some ( fn_sig) = fn_sig
181
- && !fn_sig. header . is_const ( )
182
- && const_stab. is_some ( )
183
- {
184
- self . tcx . dcx ( ) . emit_err ( errors:: MissingConstErr { fn_sig_span : fn_sig. span } ) ;
185
- }
186
-
187
- // If this is marked const *stable*, it must also be regular-stable.
188
- if let Some ( ( const_stab, const_span) ) = const_stab
189
- && let Some ( fn_sig) = fn_sig
190
- && const_stab. is_const_stable ( )
191
- && !stab. is_some_and ( |( s, _) | s. is_stable ( ) )
192
- {
193
- self . tcx
194
- . dcx ( )
195
- . emit_err ( errors:: ConstStableNotStable { fn_sig_span : fn_sig. span , const_span } ) ;
196
- }
197
-
198
- // Stable *language* features shouldn't be used as unstable library features.
199
- // (Not doing this for stable library features is checked by tidy.)
200
- if let Some ( (
201
- ConstStability { level : Unstable { .. } , feature : Some ( feature) , .. } ,
202
- const_span,
203
- ) ) = const_stab
204
- {
205
- if ACCEPTED_LANG_FEATURES . iter ( ) . find ( |f| f. name == feature) . is_some ( ) {
206
- self . tcx . dcx ( ) . emit_err ( errors:: UnstableAttrForAlreadyStableFeature {
207
- span : const_span,
208
- item_sp,
209
- } ) ;
210
- }
211
- }
212
-
213
- let const_stab = const_stab. map ( |( const_stab, _span) | {
214
- self . index . const_stab_map . insert ( def_id, const_stab) ;
215
- const_stab
216
- } ) ;
217
-
218
- // `impl const Trait for Type` items forward their const stability to their
219
- // immediate children.
220
- // FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
221
- // Currently, once that is set, we do not inherit anything from the parent any more.
222
- if const_stab. is_none ( ) {
223
- debug ! ( "annotate: const_stab not found, parent = {:?}" , self . parent_const_stab) ;
224
- if let Some ( parent) = self . parent_const_stab {
225
- if parent. is_const_unstable ( ) {
226
- self . index . const_stab_map . insert ( def_id, parent) ;
227
- }
228
- }
229
- }
230
-
231
174
if let Some ( ( depr, span) ) = & depr
232
175
&& depr. is_since_rustc_version ( )
233
176
&& stab. is_none ( )
@@ -294,15 +237,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
294
237
self . index . implications . insert ( implied_by, feature) ;
295
238
}
296
239
297
- if let Some ( ConstStability {
298
- level : Unstable { implied_by : Some ( implied_by) , .. } ,
299
- feature,
300
- ..
301
- } ) = const_stab
302
- {
303
- self . index . implications . insert ( implied_by, feature. unwrap ( ) ) ;
304
- }
305
-
306
240
self . index . stab_map . insert ( def_id, stab) ;
307
241
stab
308
242
} ) ;
@@ -316,6 +250,91 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
316
250
}
317
251
}
318
252
253
+ let final_stab = self . index . stab_map . get ( & def_id) ;
254
+
255
+ // # Const stability
256
+
257
+ let const_stab = attr:: find_const_stability ( self . tcx . sess , attrs, item_sp) ;
258
+
259
+ // If the current node is a function with const stability attributes (directly given or
260
+ // implied), check if the function/method is const.
261
+ if let Some ( fn_sig) = fn_sig
262
+ && !fn_sig. header . is_const ( )
263
+ && const_stab. is_some ( )
264
+ {
265
+ self . tcx . dcx ( ) . emit_err ( errors:: MissingConstErr { fn_sig_span : fn_sig. span } ) ;
266
+ }
267
+
268
+ // If this is marked const *stable*, it must also be regular-stable.
269
+ if let Some ( ( const_stab, const_span) ) = const_stab
270
+ && let Some ( fn_sig) = fn_sig
271
+ && const_stab. is_const_stable ( )
272
+ && !stab. is_some_and ( |s| s. is_stable ( ) )
273
+ {
274
+ self . tcx
275
+ . dcx ( )
276
+ . emit_err ( errors:: ConstStableNotStable { fn_sig_span : fn_sig. span , const_span } ) ;
277
+ }
278
+
279
+ // Stable *language* features shouldn't be used as unstable library features.
280
+ // (Not doing this for stable library features is checked by tidy.)
281
+ if let Some ( ( ConstStability { level : Unstable { .. } , feature, .. } , const_span) ) =
282
+ const_stab
283
+ {
284
+ if ACCEPTED_LANG_FEATURES . iter ( ) . find ( |f| f. name == feature) . is_some ( ) {
285
+ self . tcx . dcx ( ) . emit_err ( errors:: UnstableAttrForAlreadyStableFeature {
286
+ span : const_span,
287
+ item_sp,
288
+ } ) ;
289
+ }
290
+ }
291
+
292
+ // After checking the immediate attributes, get rid of the span and compute implied
293
+ // const stability: inherit feature gate from regular stability.
294
+ let mut const_stab = const_stab. map ( |( stab, _span) | stab) ;
295
+
296
+ // If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
297
+ if fn_sig. is_some_and ( |s| s. header . is_const ( ) ) && const_stab. is_none ( ) &&
298
+ // We only ever inherit unstable features.
299
+ let Some ( inherit_regular_stab) =
300
+ final_stab. filter ( |s| s. is_unstable ( ) )
301
+ {
302
+ const_stab = Some ( ConstStability {
303
+ // We subject these implicitly-const functions to recursive const stability.
304
+ const_stable_indirect : true ,
305
+ promotable : false ,
306
+ level : inherit_regular_stab. level ,
307
+ feature : inherit_regular_stab. feature ,
308
+ } ) ;
309
+ }
310
+
311
+ // Now that everything is computed, insert it into the table.
312
+ const_stab. inspect ( |const_stab| {
313
+ self . index . const_stab_map . insert ( def_id, * const_stab) ;
314
+ } ) ;
315
+
316
+ if let Some ( ConstStability {
317
+ level : Unstable { implied_by : Some ( implied_by) , .. } ,
318
+ feature,
319
+ ..
320
+ } ) = const_stab
321
+ {
322
+ self . index . implications . insert ( implied_by, feature) ;
323
+ }
324
+
325
+ // `impl const Trait for Type` items forward their const stability to their
326
+ // immediate children.
327
+ // FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
328
+ // Currently, once that is set, we do not inherit anything from the parent any more.
329
+ if const_stab. is_none ( ) {
330
+ debug ! ( "annotate: const_stab not found, parent = {:?}" , self . parent_const_stab) ;
331
+ if let Some ( parent) = self . parent_const_stab {
332
+ if parent. is_const_unstable ( ) {
333
+ self . index . const_stab_map . insert ( def_id, parent) ;
334
+ }
335
+ }
336
+ }
337
+
319
338
self . recurse_with_stability_attrs (
320
339
depr. map ( |( d, _) | DeprecationEntry :: local ( d, def_id) ) ,
321
340
stab,
@@ -570,13 +589,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
570
589
}
571
590
}
572
591
573
- fn check_missing_or_wrong_const_stability ( & self , def_id : LocalDefId , span : Span ) {
574
- // The visitor runs for "unstable-if-unmarked" crates, but we don't yet support
575
- // that on the const side.
576
- if !self . tcx . features ( ) . staged_api ( ) {
577
- return ;
578
- }
579
-
592
+ fn check_missing_const_stability ( & self , def_id : LocalDefId , span : Span ) {
580
593
// if the const impl is derived using the `derive_const` attribute,
581
594
// then it would be "stable" at least for the impl.
582
595
// We gate usages of it using `feature(const_trait_impl)` anyways
@@ -587,12 +600,12 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
587
600
588
601
let is_const = self . tcx . is_const_fn ( def_id. to_def_id ( ) )
589
602
|| self . tcx . is_const_trait_impl ( def_id. to_def_id ( ) ) ;
590
- let is_stable =
591
- self . tcx . lookup_stability ( def_id) . is_some_and ( |stability| stability. level . is_stable ( ) ) ;
592
- let missing_const_stability_attribute =
593
- self . tcx . lookup_const_stability ( def_id) . is_none_or ( |s| s. feature . is_none ( ) ) ;
594
603
595
- if is_const && is_stable && missing_const_stability_attribute {
604
+ // Reachable const fn must have a stability attribute.
605
+ if is_const
606
+ && self . effective_visibilities . is_reachable ( def_id)
607
+ && self . tcx . lookup_const_stability ( def_id) . is_none ( )
608
+ {
596
609
let descr = self . tcx . def_descr ( def_id. to_def_id ( ) ) ;
597
610
self . tcx . dcx ( ) . emit_err ( errors:: MissingConstStabAttr { span, descr } ) ;
598
611
}
@@ -620,7 +633,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
620
633
}
621
634
622
635
// Ensure stable `const fn` have a const stability attribute.
623
- self . check_missing_or_wrong_const_stability ( i. owner_id . def_id , i. span ) ;
636
+ self . check_missing_const_stability ( i. owner_id . def_id , i. span ) ;
624
637
625
638
intravisit:: walk_item ( self , i)
626
639
}
@@ -634,7 +647,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
634
647
let impl_def_id = self . tcx . hir ( ) . get_parent_item ( ii. hir_id ( ) ) ;
635
648
if self . tcx . impl_trait_ref ( impl_def_id) . is_none ( ) {
636
649
self . check_missing_stability ( ii. owner_id . def_id , ii. span ) ;
637
- self . check_missing_or_wrong_const_stability ( ii. owner_id . def_id , ii. span ) ;
650
+ self . check_missing_const_stability ( ii. owner_id . def_id , ii. span ) ;
638
651
}
639
652
intravisit:: walk_impl_item ( self , ii) ;
640
653
}
@@ -765,23 +778,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
765
778
// For implementations of traits, check the stability of each item
766
779
// individually as it's possible to have a stable trait with unstable
767
780
// items.
768
- hir:: ItemKind :: Impl ( hir:: Impl {
769
- constness,
770
- of_trait : Some ( ref t) ,
771
- self_ty,
772
- items,
773
- ..
774
- } ) => {
781
+ hir:: ItemKind :: Impl ( hir:: Impl { of_trait : Some ( ref t) , self_ty, items, .. } ) => {
775
782
let features = self . tcx . features ( ) ;
776
783
if features. staged_api ( ) {
777
784
let attrs = self . tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
778
785
let stab = attr:: find_stability ( self . tcx . sess , attrs, item. span ) ;
779
- let const_stab = attr:: find_const_stability (
780
- self . tcx . sess ,
781
- attrs,
782
- item. span ,
783
- matches ! ( constness, Constness :: Const ) ,
784
- ) ;
786
+ let const_stab = attr:: find_const_stability ( self . tcx . sess , attrs, item. span ) ;
785
787
786
788
// If this impl block has an #[unstable] attribute, give an
787
789
// error if all involved types and traits are stable, because
0 commit comments