@@ -139,7 +139,7 @@ pub enum StabilityLevel {
139139 /// `#[stable]`
140140 Stable {
141141 /// Rust release which stabilized this feature.
142- since : Since ,
142+ since : StableSince ,
143143 /// Is this item allowed to be referred to on stable, despite being contained in unstable
144144 /// modules?
145145 allowed_through_unstable_modules : bool ,
@@ -149,7 +149,7 @@ pub enum StabilityLevel {
149149/// Rust release in which a feature is stabilized.
150150#[ derive( Encodable , Decodable , PartialEq , Copy , Clone , Debug , Eq , Hash ) ]
151151#[ derive( HashStable_Generic ) ]
152- pub enum Since {
152+ pub enum StableSince {
153153 Version ( RustcVersion ) ,
154154 /// Stabilized in the upcoming version, whatever number that is.
155155 Current ,
@@ -378,16 +378,16 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
378378
379379 let since = if let Some ( since) = since {
380380 if since. as_str ( ) == VERSION_PLACEHOLDER {
381- Since :: Current
381+ StableSince :: Current
382382 } else if let Some ( version) = parse_version ( since) {
383- Since :: Version ( version)
383+ StableSince :: Version ( version)
384384 } else {
385385 sess. emit_err ( session_diagnostics:: InvalidSince { span : attr. span } ) ;
386- Since :: Err
386+ StableSince :: Err
387387 }
388388 } else {
389389 sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) ;
390- Since :: Err
390+ StableSince :: Err
391391 } ;
392392
393393 match feature {
@@ -720,17 +720,49 @@ pub fn eval_condition(
720720
721721#[ derive( Copy , Debug , Encodable , Decodable , Clone , HashStable_Generic ) ]
722722pub struct Deprecation {
723- pub since : Option < Symbol > ,
723+ pub since : DeprecatedSince ,
724724 /// The note to issue a reason.
725725 pub note : Option < Symbol > ,
726726 /// A text snippet used to completely replace any use of the deprecated item in an expression.
727727 ///
728728 /// This is currently unstable.
729729 pub suggestion : Option < Symbol > ,
730+ }
731+
732+ /// Release in which an API is deprecated.
733+ #[ derive( Copy , Debug , Encodable , Decodable , Clone , HashStable_Generic ) ]
734+ pub enum DeprecatedSince {
735+ RustcVersion ( RustcVersion ) ,
736+ /// Deprecated in the future ("to be determined").
737+ Future ,
738+ /// `feature(staged_api)` is off. Deprecation versions outside the standard
739+ /// library are allowed to be arbitrary strings, for better or worse.
740+ NonStandard ( Symbol ) ,
741+ /// Deprecation version is unspecified but optional.
742+ Unspecified ,
743+ /// Failed to parse a deprecation version, or the deprecation version is
744+ /// unspecified and required. An error has already been emitted.
745+ Err ,
746+ }
747+
748+ impl Deprecation {
749+ /// Whether an item marked with #[deprecated(since = "X")] is currently
750+ /// deprecated (i.e., whether X is not greater than the current rustc
751+ /// version).
752+ pub fn is_in_effect ( & self ) -> bool {
753+ match self . since {
754+ DeprecatedSince :: RustcVersion ( since) => since <= RustcVersion :: CURRENT ,
755+ DeprecatedSince :: Future => false ,
756+ // The `since` field doesn't have semantic purpose without `#![staged_api]`.
757+ DeprecatedSince :: NonStandard ( _) => true ,
758+ // Assume deprecation is in effect if "since" field is absent or invalid.
759+ DeprecatedSince :: Unspecified | DeprecatedSince :: Err => true ,
760+ }
761+ }
730762
731- /// Whether to treat the since attribute as being a Rust version identifier
732- /// (rather than an opaque string).
733- pub is_since_rustc_version : bool ,
763+ pub fn is_since_rustc_version ( & self ) -> bool {
764+ matches ! ( self . since , DeprecatedSince :: RustcVersion ( _ ) )
765+ }
734766}
735767
736768/// Finds the deprecation attribute. `None` if none exists.
@@ -839,22 +871,30 @@ pub fn find_deprecation(
839871 }
840872 }
841873
842- if is_rustc {
843- if since. is_none ( ) {
844- sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) ;
845- continue ;
874+ let since = if let Some ( since) = since {
875+ if since. as_str ( ) == "TBD" {
876+ DeprecatedSince :: Future
877+ } else if !is_rustc {
878+ DeprecatedSince :: NonStandard ( since)
879+ } else if let Some ( version) = parse_version ( since) {
880+ DeprecatedSince :: RustcVersion ( version)
881+ } else {
882+ sess. emit_err ( session_diagnostics:: InvalidSince { span : attr. span } ) ;
883+ DeprecatedSince :: Err
846884 }
885+ } else if is_rustc {
886+ sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) ;
887+ DeprecatedSince :: Err
888+ } else {
889+ DeprecatedSince :: Unspecified
890+ } ;
847891
848- if note. is_none ( ) {
849- sess. emit_err ( session_diagnostics:: MissingNote { span : attr. span } ) ;
850- continue ;
851- }
892+ if is_rustc && note. is_none ( ) {
893+ sess. emit_err ( session_diagnostics:: MissingNote { span : attr. span } ) ;
894+ continue ;
852895 }
853896
854- depr = Some ( (
855- Deprecation { since, note, suggestion, is_since_rustc_version : is_rustc } ,
856- attr. span ,
857- ) ) ;
897+ depr = Some ( ( Deprecation { since, note, suggestion } , attr. span ) ) ;
858898 }
859899
860900 depr
0 commit comments