@@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag;
1616use rustc_session:: lint:: builtin:: UNEXPECTED_CFGS ;
1717use rustc_session:: parse:: feature_err;
1818use rustc_session:: { RustcVersion , Session } ;
19+ use rustc_span:: Span ;
1920use rustc_span:: hygiene:: Transparency ;
2021use rustc_span:: symbol:: { Symbol , kw, sym} ;
21- use rustc_span:: { DUMMY_SP , Span } ;
2222
2323use crate :: fluent_generated;
2424use crate :: session_diagnostics:: { self , IncorrectReprFormatGenericCause } ;
@@ -92,13 +92,15 @@ impl Stability {
9292#[ derive( HashStable_Generic ) ]
9393pub struct ConstStability {
9494 pub level : StabilityLevel ,
95- /// This can be `None` for functions that are not even const-unstable, but
96- /// are tracked here for the purpose of `safe_to_expose_on_stable`.
95+ /// Says whether this function has an explicit `rustc_const_(un)stable` attribute.
96+ /// If `false`, the const stability information was inferred from the regular
97+ /// stability information.
98+ pub has_const_stable_attr : bool ,
99+ /// This can be `None` for functions that are not const-callable from outside code under any
100+ /// feature gate, but are tracked here for the purpose of `safe_to_expose_on_stable`.
97101 pub feature : Option < Symbol > ,
98- /// A function that is marked as "safe to expose on stable" must not use any unstable const
99- /// language features or intrinsics, and all the functions it calls must also be safe to expose
100- /// on stable. If `level` is `Stable`, this must be `true`.
101- pub safe_to_expose_on_stable : bool ,
102+ /// This is true iff the `const_stable_indirect` attribute is present.
103+ pub const_stable_indirect : bool ,
102104 /// whether the function has a `#[rustc_promotable]` attribute
103105 pub promotable : bool ,
104106}
@@ -274,14 +276,10 @@ pub fn find_stability(
274276
275277/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
276278/// attributes in `attrs`. Returns `None` if no stability attributes are found.
277- ///
278- /// `inherited_feature_gate` says which feature gate this function should be under if it doesn't
279- /// declare a gate itself, but has `#[rustc_const_stable_indirect]`.
280279pub fn find_const_stability (
281280 sess : & Session ,
282281 attrs : & [ Attribute ] ,
283282 item_sp : Span ,
284- inherited_feature_gate : Option < Symbol > ,
285283) -> Option < ( ConstStability , Span ) > {
286284 let mut const_stab: Option < ( ConstStability , Span ) > = None ;
287285 let mut promotable = false ;
@@ -302,8 +300,9 @@ pub fn find_const_stability(
302300 const_stab = Some ( (
303301 ConstStability {
304302 level,
303+ has_const_stable_attr : true ,
305304 feature : Some ( feature) ,
306- safe_to_expose_on_stable : false ,
305+ const_stable_indirect : false ,
307306 promotable : false ,
308307 } ,
309308 attr. span ,
@@ -320,8 +319,9 @@ pub fn find_const_stability(
320319 const_stab = Some ( (
321320 ConstStability {
322321 level,
322+ has_const_stable_attr : true ,
323323 feature : Some ( feature) ,
324- safe_to_expose_on_stable : true ,
324+ const_stable_indirect : false ,
325325 promotable : false ,
326326 } ,
327327 attr. span ,
@@ -347,36 +347,69 @@ pub fn find_const_stability(
347347 match & mut const_stab {
348348 Some ( ( stab, _) ) => {
349349 if stab. is_const_unstable ( ) {
350- stab. safe_to_expose_on_stable = true ;
350+ stab. const_stable_indirect = true ;
351351 } else {
352352 _ = sess. dcx ( ) . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing {
353353 span : item_sp,
354354 } )
355355 }
356356 }
357357 _ => {
358- // `#[rustc_const_stable_indirect]` implicitly makes the function unstably const,
359- // inheriting the feature gate from `#[unstable]` if it xists, or without any
360- // feature gate otherwise.
361- let c = ConstStability {
362- feature : inherited_feature_gate,
363- safe_to_expose_on_stable : true ,
364- promotable : false ,
365- level : StabilityLevel :: Unstable {
366- reason : UnstableReason :: Default ,
367- issue : None ,
368- is_soft : false ,
369- implied_by : None ,
370- } ,
371- } ;
372- const_stab = Some ( ( c, DUMMY_SP ) ) ;
358+ // We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
359+ // the `default_const_unstable` logic.
373360 }
374361 }
375362 }
376363
377364 const_stab
378365}
379366
367+ /// Called for `fn` that don't have a const stability.
368+ ///
369+ /// `effective_reg_stability` must be the effecive regular stability, i.e. after applying all the
370+ /// rules about "inherited" stability.
371+ pub fn default_const_stability (
372+ _sess : & Session ,
373+ is_const_fn : bool ,
374+ attrs : & [ Attribute ] ,
375+ effective_reg_stability : Option < & Stability > ,
376+ ) -> Option < ConstStability > {
377+ let const_stable_indirect =
378+ attrs. iter ( ) . any ( |a| a. name_or_empty ( ) == sym:: rustc_const_stable_indirect) ;
379+ // Intrinsics are *not* `const fn` here, and yet we want to add a default const stability
380+ // for them if they are marked `const_stable_indirect`.
381+ if ( is_const_fn || const_stable_indirect)
382+ && let Some ( reg_stability) = effective_reg_stability
383+ && reg_stability. level . is_unstable ( )
384+ {
385+ // This has a feature gate, reuse that for const stability.
386+ // We only want to do this if it is an unstable feature gate.
387+ Some ( ConstStability {
388+ feature : Some ( reg_stability. feature ) ,
389+ has_const_stable_attr : false ,
390+ const_stable_indirect,
391+ promotable : false ,
392+ level : reg_stability. level ,
393+ } )
394+ } else if const_stable_indirect {
395+ // Make it const-unstable without a feature gate, to record the `const_stable_indirect`.
396+ Some ( ConstStability {
397+ feature : None ,
398+ has_const_stable_attr : false ,
399+ const_stable_indirect,
400+ promotable : false ,
401+ level : StabilityLevel :: Unstable {
402+ reason : UnstableReason :: Default ,
403+ issue : None ,
404+ is_soft : false ,
405+ implied_by : None ,
406+ } ,
407+ } )
408+ } else {
409+ None
410+ }
411+ }
412+
380413/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
381414/// Returns `None` if no stability attributes are found.
382415pub fn find_body_stability (
0 commit comments