@@ -13,6 +13,7 @@ use rustc_session::parse::{feature_err, ParseSess};
1313use rustc_session:: Session ;
1414use rustc_span:: hygiene:: Transparency ;
1515use rustc_span:: { symbol:: sym, symbol:: Symbol , Span } ;
16+ use std:: fmt:: { self , Display } ;
1617use std:: num:: NonZeroU32 ;
1718
1819use crate :: session_diagnostics:: { self , IncorrectReprFormatGenericCause } ;
@@ -23,10 +24,7 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
2324/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
2425pub const VERSION_PLACEHOLDER : & str = "CURRENT_RUSTC_VERSION" ;
2526
26- pub fn rust_version_symbol ( ) -> Symbol {
27- let version = option_env ! ( "CFG_RELEASE" ) . unwrap_or ( "<current>" ) ;
28- Symbol :: intern ( & version)
29- }
27+ pub const CURRENT_RUSTC_VERSION : & str = env ! ( "CFG_RELEASE" ) ;
3028
3129pub fn is_builtin_attr ( attr : & Attribute ) -> bool {
3230 attr. is_doc_comment ( ) || attr. ident ( ) . is_some_and ( |ident| is_builtin_attr_name ( ident. name ) )
@@ -144,13 +142,24 @@ pub enum StabilityLevel {
144142 /// `#[stable]`
145143 Stable {
146144 /// Rust release which stabilized this feature.
147- since : Symbol ,
145+ since : Since ,
148146 /// Is this item allowed to be referred to on stable, despite being contained in unstable
149147 /// modules?
150148 allowed_through_unstable_modules : bool ,
151149 } ,
152150}
153151
152+ /// Rust release in which a feature is stabilized.
153+ #[ derive( Encodable , Decodable , PartialEq , Copy , Clone , Debug , Eq , Hash ) ]
154+ #[ derive( HashStable_Generic ) ]
155+ pub enum Since {
156+ Version ( Version ) ,
157+ /// Stabilized in the upcoming version, whatever number that is.
158+ Current ,
159+ /// Failed to parse a stabilization version.
160+ Err ,
161+ }
162+
154163impl StabilityLevel {
155164 pub fn is_unstable ( & self ) -> bool {
156165 matches ! ( self , StabilityLevel :: Unstable { .. } )
@@ -372,22 +381,24 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
372381
373382 let since = if let Some ( since) = since {
374383 if since. as_str ( ) == VERSION_PLACEHOLDER {
375- Ok ( rust_version_symbol ( ) )
376- } else if parse_version ( since. as_str ( ) , false ) . is_some ( ) {
377- Ok ( since )
384+ Since :: Current
385+ } else if let Some ( version ) = parse_version ( since. as_str ( ) , false ) {
386+ Since :: Version ( version )
378387 } else {
379- Err ( sess. emit_err ( session_diagnostics:: InvalidSince { span : attr. span } ) )
388+ sess. emit_err ( session_diagnostics:: InvalidSince { span : attr. span } ) ;
389+ Since :: Err
380390 }
381391 } else {
382- Err ( sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) )
392+ sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) ;
393+ Since :: Err
383394 } ;
384395
385- match ( feature, since ) {
386- ( Ok ( feature) , Ok ( since ) ) => {
396+ match feature {
397+ Ok ( feature) => {
387398 let level = StabilityLevel :: Stable { since, allowed_through_unstable_modules : false } ;
388399 Some ( ( feature, level) )
389400 }
390- ( Err ( ErrorGuaranteed { .. } ) , _ ) | ( _ , Err ( ErrorGuaranteed { .. } ) ) => None ,
401+ Err ( ErrorGuaranteed { .. } ) => None ,
391402 }
392403}
393404
@@ -556,11 +567,12 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
556567 }
557568}
558569
559- #[ derive( Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
560- struct Version {
561- major : u16 ,
562- minor : u16 ,
563- patch : u16 ,
570+ #[ derive( Encodable , Decodable , Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
571+ #[ derive( HashStable_Generic ) ]
572+ pub struct Version {
573+ pub major : u16 ,
574+ pub minor : u16 ,
575+ pub patch : u16 ,
564576}
565577
566578fn parse_version ( s : & str , allow_appendix : bool ) -> Option < Version > {
@@ -576,6 +588,12 @@ fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
576588 Some ( Version { major, minor, patch } )
577589}
578590
591+ impl Display for Version {
592+ fn fmt ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
593+ write ! ( formatter, "{}.{}.{}" , self . major, self . minor, self . patch)
594+ }
595+ }
596+
579597/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
580598/// evaluate individual items.
581599pub fn eval_condition (
@@ -609,7 +627,7 @@ pub fn eval_condition(
609627 sess. emit_warning ( session_diagnostics:: UnknownVersionLiteral { span : * span } ) ;
610628 return false ;
611629 } ;
612- let rustc_version = parse_version ( env ! ( "CFG_RELEASE" ) , true ) . unwrap ( ) ;
630+ let rustc_version = parse_version ( CURRENT_RUSTC_VERSION , true ) . unwrap ( ) ;
613631
614632 // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
615633 if sess. assume_incomplete_release {
0 commit comments