@@ -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}
@@ -275,22 +277,21 @@ pub fn find_stability(
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.
277279///
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] `.
280+ /// The second component is the `const_stable_indirect` attribute if present, which can be meaningful
281+ /// even if there is no `rustc_const_stable`/`rustc_const_unstable `.
280282pub fn find_const_stability (
281283 sess : & Session ,
282284 attrs : & [ Attribute ] ,
283285 item_sp : Span ,
284- inherited_feature_gate : Option < Symbol > ,
285- ) -> Option < ( ConstStability , Span ) > {
286+ ) -> ( Option < ( ConstStability , Span ) > , Option < Span > ) {
286287 let mut const_stab: Option < ( ConstStability , Span ) > = None ;
287288 let mut promotable = false ;
288- let mut const_stable_indirect = false ;
289+ let mut const_stable_indirect = None ;
289290
290291 for attr in attrs {
291292 match attr. name_or_empty ( ) {
292293 sym:: rustc_promotable => promotable = true ,
293- sym:: rustc_const_stable_indirect => const_stable_indirect = true ,
294+ sym:: rustc_const_stable_indirect => const_stable_indirect = Some ( attr . span ) ,
294295 sym:: rustc_const_unstable => {
295296 if const_stab. is_some ( ) {
296297 sess. dcx ( )
@@ -302,8 +303,9 @@ pub fn find_const_stability(
302303 const_stab = Some ( (
303304 ConstStability {
304305 level,
306+ has_const_stable_attr : true ,
305307 feature : Some ( feature) ,
306- safe_to_expose_on_stable : false ,
308+ const_stable_indirect : false ,
307309 promotable : false ,
308310 } ,
309311 attr. span ,
@@ -320,8 +322,9 @@ pub fn find_const_stability(
320322 const_stab = Some ( (
321323 ConstStability {
322324 level,
325+ has_const_stable_attr : true ,
323326 feature : Some ( feature) ,
324- safe_to_expose_on_stable : true ,
327+ const_stable_indirect : false ,
325328 promotable : false ,
326329 } ,
327330 attr. span ,
@@ -343,38 +346,69 @@ pub fn find_const_stability(
343346 }
344347 }
345348 }
346- if const_stable_indirect {
349+ if const_stable_indirect. is_some ( ) {
347350 match & mut const_stab {
348351 Some ( ( stab, _) ) => {
349352 if stab. is_const_unstable ( ) {
350- stab. safe_to_expose_on_stable = true ;
353+ stab. const_stable_indirect = true ;
351354 } else {
352355 _ = sess. dcx ( ) . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing {
353356 span : item_sp,
354357 } )
355358 }
356359 }
357360 _ => {
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 ) ) ;
361+ // We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
362+ // the `default_const_unstable` logic.
373363 }
374364 }
375365 }
376366
377- const_stab
367+ ( const_stab, const_stable_indirect)
368+ }
369+
370+ /// Called for `fn` that don't have a const stability.
371+ ///
372+ /// `effective_reg_stability` must be the effecive regular stability, i.e. after applying all the
373+ /// rules about "inherited" stability.
374+ pub fn default_const_stability (
375+ _sess : & Session ,
376+ is_const_fn : bool ,
377+ const_stable_indirect : bool ,
378+ effective_reg_stability : Option < & Stability > ,
379+ ) -> Option < ConstStability > {
380+ // Intrinsics are *not* `const fn` here, and yet we want to add a default const stability
381+ // for them if they are marked `const_stable_indirect`.
382+ if ( is_const_fn || const_stable_indirect)
383+ && let Some ( reg_stability) = effective_reg_stability
384+ && reg_stability. level . is_unstable ( )
385+ {
386+ // This has a feature gate, reuse that for const stability.
387+ // We only want to do this if it is an unstable feature gate.
388+ Some ( ConstStability {
389+ feature : Some ( reg_stability. feature ) ,
390+ has_const_stable_attr : false ,
391+ const_stable_indirect,
392+ promotable : false ,
393+ level : reg_stability. level ,
394+ } )
395+ } else if const_stable_indirect {
396+ // Make it const-unstable without a feature gate, to record the `const_stable_indirect`.
397+ Some ( ConstStability {
398+ feature : None ,
399+ has_const_stable_attr : false ,
400+ const_stable_indirect,
401+ promotable : false ,
402+ level : StabilityLevel :: Unstable {
403+ reason : UnstableReason :: Default ,
404+ issue : None ,
405+ is_soft : false ,
406+ implied_by : None ,
407+ } ,
408+ } )
409+ } else {
410+ None
411+ }
378412}
379413
380414/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
0 commit comments