@@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag;
16
16
use rustc_session:: lint:: builtin:: UNEXPECTED_CFGS ;
17
17
use rustc_session:: parse:: feature_err;
18
18
use rustc_session:: { RustcVersion , Session } ;
19
+ use rustc_span:: Span ;
19
20
use rustc_span:: hygiene:: Transparency ;
20
21
use rustc_span:: symbol:: { Symbol , kw, sym} ;
21
- use rustc_span:: { DUMMY_SP , Span } ;
22
22
23
23
use crate :: fluent_generated;
24
24
use crate :: session_diagnostics:: { self , IncorrectReprFormatGenericCause } ;
@@ -92,13 +92,15 @@ impl Stability {
92
92
#[ derive( HashStable_Generic ) ]
93
93
pub struct ConstStability {
94
94
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`.
97
101
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 ,
102
104
/// whether the function has a `#[rustc_promotable]` attribute
103
105
pub promotable : bool ,
104
106
}
@@ -275,22 +277,21 @@ pub fn find_stability(
275
277
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
276
278
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
277
279
///
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 `.
280
282
pub fn find_const_stability (
281
283
sess : & Session ,
282
284
attrs : & [ Attribute ] ,
283
285
item_sp : Span ,
284
- inherited_feature_gate : Option < Symbol > ,
285
- ) -> Option < ( ConstStability , Span ) > {
286
+ ) -> ( Option < ( ConstStability , Span ) > , Option < Span > ) {
286
287
let mut const_stab: Option < ( ConstStability , Span ) > = None ;
287
288
let mut promotable = false ;
288
- let mut const_stable_indirect = false ;
289
+ let mut const_stable_indirect = None ;
289
290
290
291
for attr in attrs {
291
292
match attr. name_or_empty ( ) {
292
293
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 ) ,
294
295
sym:: rustc_const_unstable => {
295
296
if const_stab. is_some ( ) {
296
297
sess. dcx ( )
@@ -302,8 +303,9 @@ pub fn find_const_stability(
302
303
const_stab = Some ( (
303
304
ConstStability {
304
305
level,
306
+ has_const_stable_attr : true ,
305
307
feature : Some ( feature) ,
306
- safe_to_expose_on_stable : false ,
308
+ const_stable_indirect : false ,
307
309
promotable : false ,
308
310
} ,
309
311
attr. span ,
@@ -320,8 +322,9 @@ pub fn find_const_stability(
320
322
const_stab = Some ( (
321
323
ConstStability {
322
324
level,
325
+ has_const_stable_attr : true ,
323
326
feature : Some ( feature) ,
324
- safe_to_expose_on_stable : true ,
327
+ const_stable_indirect : false ,
325
328
promotable : false ,
326
329
} ,
327
330
attr. span ,
@@ -343,38 +346,69 @@ pub fn find_const_stability(
343
346
}
344
347
}
345
348
}
346
- if const_stable_indirect {
349
+ if const_stable_indirect. is_some ( ) {
347
350
match & mut const_stab {
348
351
Some ( ( stab, _) ) => {
349
352
if stab. is_const_unstable ( ) {
350
- stab. safe_to_expose_on_stable = true ;
353
+ stab. const_stable_indirect = true ;
351
354
} else {
352
355
_ = sess. dcx ( ) . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing {
353
356
span : item_sp,
354
357
} )
355
358
}
356
359
}
357
360
_ => {
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.
373
363
}
374
364
}
375
365
}
376
366
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
+ }
378
412
}
379
413
380
414
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
0 commit comments